PageRenderTime 58ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/test/jenkins-results-parser/src/main/java/com/liferay/jenkins/results/parser/GitHubDevSyncUtil.java

http://github.com/liferay/liferay-portal
Java | 1417 lines | 1032 code | 368 blank | 17 comment | 107 complexity | 200996d7534ad064d5fcd0f8afcb507c MD5 | raw file
Possible License(s): LGPL-2.0
  1. /**
  2. * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
  3. *
  4. * This library is free software; you can redistribute it and/or modify it under
  5. * the terms of the GNU Lesser General Public License as published by the Free
  6. * Software Foundation; either version 2.1 of the License, or (at your option)
  7. * any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful, but WITHOUT
  10. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  12. * details.
  13. */
  14. package com.liferay.jenkins.results.parser;
  15. import java.io.File;
  16. import java.io.IOException;
  17. import java.util.ArrayList;
  18. import java.util.Collections;
  19. import java.util.HashMap;
  20. import java.util.HashSet;
  21. import java.util.List;
  22. import java.util.Map;
  23. import java.util.Set;
  24. import java.util.concurrent.Callable;
  25. import java.util.concurrent.ThreadPoolExecutor;
  26. import java.util.regex.Matcher;
  27. import java.util.regex.Pattern;
  28. /**
  29. * @author Michael Hashimoto
  30. * @author Peter Yoo
  31. */
  32. public class GitHubDevSyncUtil {
  33. public static void clone(String repositoryName, File workingDirectory) {
  34. List<String> usedGitHubDevRemoteHostnames = new ArrayList<>();
  35. while (true) {
  36. String gitHubDevRemoteHostname =
  37. JenkinsResultsParserUtil.getRandomGitHubDevNodeHostname(
  38. usedGitHubDevRemoteHostnames);
  39. usedGitHubDevRemoteHostnames.add(gitHubDevRemoteHostname);
  40. String gitHubDevRemoteURL = JenkinsResultsParserUtil.combine(
  41. "git@", gitHubDevRemoteHostname, ":liferay/", repositoryName);
  42. try {
  43. GitUtil.clone(gitHubDevRemoteURL, workingDirectory);
  44. }
  45. catch (Exception exception) {
  46. String message = JenkinsResultsParserUtil.combine(
  47. "Unable to clone ", repositoryName, " from ",
  48. gitHubDevRemoteURL, ".");
  49. if (usedGitHubDevRemoteHostnames.size() == 3) {
  50. throw new RuntimeException(message, exception);
  51. }
  52. System.out.println("Retrying: " + message);
  53. }
  54. break;
  55. }
  56. }
  57. public static LocalGitBranch createCacheLocalGitBranch(
  58. LocalGitRepository localGitRepository, LocalGitBranch localGitBranch,
  59. boolean synchronize) {
  60. return _createCacheLocalGitBranch(
  61. localGitRepository, "liferay", localGitBranch.getName(), "liferay",
  62. localGitBranch.getSHA(), localGitBranch.getSHA(), synchronize);
  63. }
  64. public static LocalGitBranch createCacheLocalGitBranch(
  65. LocalGitRepository localGitRepository, PullRequest pullRequest,
  66. boolean synchronize) {
  67. return _createCacheLocalGitBranch(
  68. localGitRepository, pullRequest.getReceiverUsername(),
  69. pullRequest.getSenderBranchName(), pullRequest.getSenderUsername(),
  70. pullRequest.getSenderSHA(), pullRequest.getLiferayRemoteBranchSHA(),
  71. synchronize);
  72. }
  73. public static LocalGitBranch createCacheLocalGitBranch(
  74. LocalGitRepository localGitRepository, RemoteGitRef remoteGitRef,
  75. boolean synchronize) {
  76. return _createCacheLocalGitBranch(
  77. localGitRepository, remoteGitRef.getUsername(),
  78. remoteGitRef.getName(), remoteGitRef.getUsername(),
  79. remoteGitRef.getSHA(), remoteGitRef.getSHA(), synchronize);
  80. }
  81. public static LocalGitBranch createCacheLocalGitBranch(
  82. LocalGitRepository localGitRepository, String name, String sha,
  83. boolean synchronize) {
  84. return _createCacheLocalGitBranch(
  85. localGitRepository, "liferay", name, "liferay", sha, sha,
  86. synchronize);
  87. }
  88. public static RemoteGitBranch fetchCacheBranchFromGitHubDev(
  89. GitWorkingDirectory gitWorkingDirectory, String cacheBranchName) {
  90. List<GitRemote> gitHubDevGitRemotes = getGitHubDevGitRemotes(
  91. gitWorkingDirectory);
  92. try {
  93. while (!gitHubDevGitRemotes.isEmpty()) {
  94. GitRemote gitHubDevGitRemote = getRandomGitRemote(
  95. gitHubDevGitRemotes);
  96. gitHubDevGitRemotes.remove(gitHubDevGitRemote);
  97. try {
  98. RemoteGitBranch cachedRemoteGitBranch =
  99. gitWorkingDirectory.getRemoteGitBranch(
  100. cacheBranchName, gitHubDevGitRemote, true);
  101. gitWorkingDirectory.fetch(cachedRemoteGitBranch);
  102. return cachedRemoteGitBranch;
  103. }
  104. catch (RuntimeException runtimeException) {
  105. String message = JenkinsResultsParserUtil.combine(
  106. "Unable to fetch cached remote Git branch ",
  107. cacheBranchName, "\n", runtimeException.getMessage());
  108. if (gitHubDevGitRemotes.isEmpty()) {
  109. System.out.println(message);
  110. throw new RuntimeException(
  111. JenkinsResultsParserUtil.combine(
  112. "Unable to fetch ", cacheBranchName,
  113. " from git@github-dev.com"),
  114. runtimeException);
  115. }
  116. System.out.println("Retrying: " + message);
  117. }
  118. finally {
  119. gitWorkingDirectory.removeGitRemote(gitHubDevGitRemote);
  120. }
  121. }
  122. return null;
  123. }
  124. finally {
  125. gitWorkingDirectory.removeGitRemotes(gitHubDevGitRemotes);
  126. }
  127. }
  128. public static String getCacheBranchName(PullRequest pullRequest) {
  129. return getCacheBranchName(
  130. pullRequest.getReceiverUsername(), pullRequest.getSenderUsername(),
  131. pullRequest.getSenderSHA(),
  132. pullRequest.getLiferayRemoteBranchSHA());
  133. }
  134. public static String getCacheBranchName(RemoteGitRef remoteGitRef) {
  135. return getCacheBranchName(
  136. remoteGitRef.getUsername(), remoteGitRef.getUsername(),
  137. remoteGitRef.getSHA(), remoteGitRef.getSHA());
  138. }
  139. public static List<GitRemote> getGitHubDevGitRemotes(
  140. GitWorkingDirectory gitWorkingDirectory) {
  141. List<String> gitHubDevRemoteURLs = getGitHubDevRemoteURLs(
  142. gitWorkingDirectory);
  143. List<GitRemote> gitHubDevGitRemotes = new ArrayList<>(
  144. gitHubDevRemoteURLs.size());
  145. for (String gitHubDevRemoteURL : gitHubDevRemoteURLs) {
  146. String gitHubDevRemoteName =
  147. "git-hub-dev-remote-" +
  148. gitHubDevRemoteURLs.indexOf(gitHubDevRemoteURL);
  149. GitRemote gitRemote = gitWorkingDirectory.getGitRemote(
  150. gitHubDevRemoteName);
  151. if ((gitRemote == null) ||
  152. !gitHubDevRemoteURL.equals(gitRemote.getRemoteURL())) {
  153. gitRemote = gitWorkingDirectory.addGitRemote(
  154. true, gitHubDevRemoteName, gitHubDevRemoteURL);
  155. }
  156. gitHubDevGitRemotes.add(gitRemote);
  157. }
  158. return gitHubDevGitRemotes;
  159. }
  160. public static String synchronizeToGitHubDev(
  161. GitWorkingDirectory gitWorkingDirectory, String receiverUsername,
  162. String senderBranchName, String senderUsername,
  163. String senderBranchSHA, String upstreamBranchSHA)
  164. throws IOException {
  165. return synchronizeToGitHubDev(
  166. gitWorkingDirectory, receiverUsername, 0, senderBranchName,
  167. senderUsername, senderBranchSHA, upstreamBranchSHA);
  168. }
  169. protected static void cacheBranch(
  170. GitWorkingDirectory gitWorkingDirectory, LocalGitBranch localGitBranch,
  171. GitRemote gitRemote, long timestamp) {
  172. RemoteGitBranch lockRemoteGitBranch = null;
  173. try {
  174. lockRemoteGitBranch = gitWorkingDirectory.pushToRemoteGitRepository(
  175. true, localGitBranch, localGitBranch.getName() + "-LOCK",
  176. gitRemote);
  177. gitWorkingDirectory.pushToRemoteGitRepository(
  178. true, localGitBranch, localGitBranch.getName(), gitRemote);
  179. gitWorkingDirectory.pushToRemoteGitRepository(
  180. true, localGitBranch,
  181. JenkinsResultsParserUtil.combine(
  182. localGitBranch.getName(), "-", String.valueOf(timestamp)),
  183. gitRemote);
  184. }
  185. finally {
  186. if (lockRemoteGitBranch != null) {
  187. gitWorkingDirectory.deleteRemoteGitBranch(lockRemoteGitBranch);
  188. }
  189. }
  190. }
  191. protected static void cacheBranches(
  192. final GitWorkingDirectory gitWorkingDirectory,
  193. final LocalGitBranch localGitBranch,
  194. List<GitRemote> gitHubDevGitRemotes, final String upstreamUsername) {
  195. String currentBranchName = gitWorkingDirectory.getCurrentBranchName();
  196. String localGitBranchName = localGitBranch.getName();
  197. if ((currentBranchName == null) ||
  198. !currentBranchName.equals(localGitBranchName)) {
  199. gitWorkingDirectory.checkoutLocalGitBranch(localGitBranch, "-f");
  200. }
  201. final long start = System.currentTimeMillis();
  202. final RemoteGitBranch upstreamRemoteGitBranch =
  203. gitWorkingDirectory.getRemoteGitBranch(
  204. gitWorkingDirectory.getUpstreamBranchName(),
  205. gitWorkingDirectory.getGitRemote("upstream"), true);
  206. List<Callable<Object>> callables = new ArrayList<>();
  207. for (final GitRemote gitHubDevGitRemote : gitHubDevGitRemotes) {
  208. Callable<Object> callable = new SafeCallable<Object>() {
  209. @Override
  210. public Object safeCall() {
  211. cacheBranch(
  212. gitWorkingDirectory, localGitBranch, gitHubDevGitRemote,
  213. start);
  214. if (upstreamUsername.equals("liferay")) {
  215. LocalGitBranch upstreamLocalGitBranch =
  216. gitWorkingDirectory.getLocalGitBranch(
  217. upstreamRemoteGitBranch.getName(), true);
  218. gitWorkingDirectory.pushToRemoteGitRepository(
  219. true, upstreamLocalGitBranch,
  220. upstreamRemoteGitBranch.getName(),
  221. gitHubDevGitRemote);
  222. }
  223. return null;
  224. }
  225. };
  226. callables.add(callable);
  227. }
  228. ParallelExecutor<Object> parallelExecutor = new ParallelExecutor<>(
  229. callables, _threadPoolExecutor);
  230. parallelExecutor.execute();
  231. long duration = System.currentTimeMillis() - start;
  232. System.out.println(
  233. "Cache branches pushed up in " +
  234. JenkinsResultsParserUtil.toDurationString(duration));
  235. }
  236. protected static void checkoutUpstreamLocalGitBranch(
  237. GitWorkingDirectory gitWorkingDirectory, String upstreamBranchSHA) {
  238. LocalGitBranch upstreamLocalGitBranch = updateUpstreamLocalGitBranch(
  239. gitWorkingDirectory, upstreamBranchSHA);
  240. if (upstreamLocalGitBranch != null) {
  241. gitWorkingDirectory.checkoutLocalGitBranch(upstreamLocalGitBranch);
  242. }
  243. }
  244. protected static void copyUpstreamRefsToHeads(
  245. GitWorkingDirectory gitWorkingDirectory)
  246. throws IOException {
  247. File gitDir = gitWorkingDirectory.getGitDirectory();
  248. File headsDir = new File(gitDir, "refs/heads");
  249. File upstreamDir = new File(gitDir, "refs/remotes/upstream-temp");
  250. for (File file : upstreamDir.listFiles()) {
  251. System.out.println(
  252. JenkinsResultsParserUtil.combine(
  253. "Copying ", headsDir.getPath(), " to ",
  254. upstreamDir.getPath()));
  255. JenkinsResultsParserUtil.copy(
  256. file, new File(headsDir, file.getName()));
  257. }
  258. }
  259. protected static void deleteCacheLocalGitBranches(
  260. String excludeBranchName, GitWorkingDirectory gitWorkingDirectory) {
  261. for (String localGitBranchName :
  262. gitWorkingDirectory.getLocalGitBranchNames()) {
  263. if (localGitBranchName.matches(_cacheBranchPattern.pattern()) &&
  264. !localGitBranchName.equals(excludeBranchName)) {
  265. gitWorkingDirectory.deleteLocalGitBranch(localGitBranchName);
  266. }
  267. }
  268. }
  269. protected static void deleteCacheRemoteGitBranch(
  270. String cacheBranchName, GitWorkingDirectory gitWorkingDirectory,
  271. Map<String, RemoteGitBranch> remoteGitBranches) {
  272. List<RemoteGitBranch> cacheRemoteGitBranches = new ArrayList<>(2);
  273. for (Map.Entry<String, RemoteGitBranch> entry :
  274. remoteGitBranches.entrySet()) {
  275. String remoteGitBranchName = entry.getKey();
  276. if (!remoteGitBranchName.startsWith(cacheBranchName)) {
  277. continue;
  278. }
  279. cacheRemoteGitBranches.add(entry.getValue());
  280. }
  281. if (!cacheRemoteGitBranches.isEmpty()) {
  282. gitWorkingDirectory.deleteRemoteGitBranches(cacheRemoteGitBranches);
  283. }
  284. }
  285. protected static void deleteExpiredCacheBranches(
  286. GitRemote gitRemote, long timestamp) {
  287. int branchCount = 0;
  288. int deleteCount = 0;
  289. long oldestBranchAge = Long.MIN_VALUE;
  290. Map<String, RemoteGitBranch> remoteGitBranches = new HashMap<>();
  291. GitWorkingDirectory gitWorkingDirectory =
  292. gitRemote.getGitWorkingDirectory();
  293. for (RemoteGitBranch remoteGitBranch :
  294. gitWorkingDirectory.getRemoteGitBranches(gitRemote)) {
  295. remoteGitBranches.put(remoteGitBranch.getName(), remoteGitBranch);
  296. }
  297. List<RemoteGitBranch> expiredRemoteGitBranches = new ArrayList<>();
  298. for (Map.Entry<String, RemoteGitBranch> entry :
  299. remoteGitBranches.entrySet()) {
  300. RemoteGitBranch remoteGitBranch = entry.getValue();
  301. String remoteGitBranchName = remoteGitBranch.getName();
  302. Matcher matcher = _cacheBranchPattern.matcher(remoteGitBranchName);
  303. if (!matcher.matches()) {
  304. continue;
  305. }
  306. String lastBlock = matcher.group(2);
  307. if (!lastBlock.matches("\\d+")) {
  308. continue;
  309. }
  310. branchCount++;
  311. long remoteGitBranchTimestamp = Long.parseLong(lastBlock);
  312. long branchAge = timestamp - remoteGitBranchTimestamp;
  313. if (branchAge > _MILLIS_BRANCH_EXPIRATION) {
  314. String gitRepositoryBaseRemoteGitBranchName =
  315. remoteGitBranchName.replaceAll("(.*)-\\d+", "$1");
  316. RemoteGitBranch gitRepositoryBaseRemoteGitBranch =
  317. remoteGitBranches.get(gitRepositoryBaseRemoteGitBranchName);
  318. if (gitRepositoryBaseRemoteGitBranch != null) {
  319. expiredRemoteGitBranches.add(
  320. gitRepositoryBaseRemoteGitBranch);
  321. }
  322. expiredRemoteGitBranches.add(remoteGitBranch);
  323. deleteCount++;
  324. }
  325. else {
  326. oldestBranchAge = Math.max(oldestBranchAge, branchAge);
  327. }
  328. }
  329. System.out.println(
  330. JenkinsResultsParserUtil.combine(
  331. "Deleting ", String.valueOf(expiredRemoteGitBranches.size()),
  332. " branches from ", gitRemote.getRemoteURL()));
  333. gitWorkingDirectory.deleteRemoteGitBranches(expiredRemoteGitBranches);
  334. System.out.println(
  335. JenkinsResultsParserUtil.combine(
  336. "Found ", String.valueOf(branchCount), " cache branches on ",
  337. gitRemote.getRemoteURL(), " ", String.valueOf(deleteCount),
  338. " were deleted. ", String.valueOf(branchCount - deleteCount),
  339. " remain. The oldest branch is ",
  340. JenkinsResultsParserUtil.toDurationString(oldestBranchAge),
  341. " old."));
  342. }
  343. protected static void deleteExpiredRemoteGitBranches(
  344. final GitWorkingDirectory gitWorkingDirectory,
  345. List<GitRemote> gitHubDevGitRemotes) {
  346. final long start = System.currentTimeMillis();
  347. List<Callable<Object>> callables = new ArrayList<>();
  348. for (final GitRemote gitHubDevGitRemote : gitHubDevGitRemotes) {
  349. Callable<Object> callable = new SafeCallable<Object>() {
  350. @Override
  351. public Object safeCall() {
  352. deleteExpiredCacheBranches(gitHubDevGitRemote, start);
  353. return null;
  354. }
  355. };
  356. callables.add(callable);
  357. }
  358. ParallelExecutor<Object> parallelExecutor = new ParallelExecutor<>(
  359. callables, _threadPoolExecutor);
  360. parallelExecutor.execute();
  361. long duration = System.currentTimeMillis() - start;
  362. System.out.println(
  363. "Expired cache branches deleted in " +
  364. JenkinsResultsParserUtil.toDurationString(duration));
  365. }
  366. protected static void deleteExtraTimestampBranches(
  367. GitRemote gitHubDevGitRemote) {
  368. GitWorkingDirectory gitWorkingDirectory =
  369. gitHubDevGitRemote.getGitWorkingDirectory();
  370. List<RemoteGitBranch> remoteGitBranches =
  371. gitWorkingDirectory.getRemoteGitBranches(gitHubDevGitRemote);
  372. Collections.sort(remoteGitBranches);
  373. Map<String, List<RemoteGitBranch>> remoteGitBranchesMap =
  374. new HashMap<>();
  375. for (RemoteGitBranch remoteGitBranch : remoteGitBranches) {
  376. String remoteGitBranchName = remoteGitBranch.getName();
  377. if (remoteGitBranchName.matches(
  378. _cacheBranchPattern.pattern() + "-\\d+")) {
  379. String baseCacheBranchName = remoteGitBranchName.replaceAll(
  380. "(.*)-\\d+", "$1");
  381. if (!remoteGitBranchesMap.containsKey(baseCacheBranchName)) {
  382. remoteGitBranchesMap.put(
  383. baseCacheBranchName, new ArrayList<RemoteGitBranch>());
  384. }
  385. List<RemoteGitBranch> timestampedRemoteGitBranches =
  386. remoteGitBranchesMap.get(baseCacheBranchName);
  387. timestampedRemoteGitBranches.add(remoteGitBranch);
  388. }
  389. }
  390. for (Map.Entry<String, List<RemoteGitBranch>> entry :
  391. remoteGitBranchesMap.entrySet()) {
  392. List<RemoteGitBranch> timestampedRemoteGitBranches =
  393. entry.getValue();
  394. if (timestampedRemoteGitBranches.size() > 1) {
  395. timestampedRemoteGitBranches.remove(
  396. timestampedRemoteGitBranches.size() - 1);
  397. gitWorkingDirectory.deleteRemoteGitBranches(
  398. timestampedRemoteGitBranches);
  399. }
  400. }
  401. }
  402. protected static void deleteExtraTimestampBranches(
  403. List<GitRemote> gitHubDevGitRemotes) {
  404. long start = System.currentTimeMillis();
  405. List<Callable<Object>> callables = new ArrayList<>();
  406. for (final GitRemote gitHubDevGitRemote : gitHubDevGitRemotes) {
  407. Callable<Object> callable = new SafeCallable<Object>() {
  408. @Override
  409. public Object safeCall() {
  410. deleteExtraTimestampBranches(gitHubDevGitRemote);
  411. return null;
  412. }
  413. };
  414. callables.add(callable);
  415. }
  416. ParallelExecutor<Object> parallelExecutor = new ParallelExecutor<>(
  417. callables, _threadPoolExecutor);
  418. parallelExecutor.execute();
  419. long duration = System.currentTimeMillis() - start;
  420. System.out.println(
  421. "Local git nodes cleaned in " +
  422. JenkinsResultsParserUtil.toDurationString(duration));
  423. }
  424. protected static void deleteFromAllRemotes(
  425. final String remoteGitBranchName, final List<GitRemote> gitRemotes) {
  426. final long start = System.currentTimeMillis();
  427. List<Callable<Boolean>> callables = new ArrayList<>();
  428. for (final GitRemote gitRemote : gitRemotes) {
  429. Callable<Boolean> callable = new SafeCallable<Boolean>() {
  430. @Override
  431. public Boolean safeCall() {
  432. GitWorkingDirectory gitWorkingDirectory =
  433. gitRemote.getGitWorkingDirectory();
  434. gitWorkingDirectory.deleteRemoteGitBranch(
  435. remoteGitBranchName, gitRemote);
  436. return true;
  437. }
  438. };
  439. callables.add(callable);
  440. }
  441. ParallelExecutor<Boolean> parallelExecutor = new ParallelExecutor<>(
  442. callables, _threadPoolExecutor);
  443. parallelExecutor.execute();
  444. long duration = System.currentTimeMillis() - start;
  445. System.out.println(
  446. JenkinsResultsParserUtil.combine(
  447. "Deleted ", remoteGitBranchName, " on ",
  448. String.valueOf(gitRemotes.size()), " git nodes in ",
  449. JenkinsResultsParserUtil.toDurationString(duration)));
  450. }
  451. protected static void deleteOrphanedCacheBranches(GitRemote gitRemote) {
  452. List<RemoteGitBranch> cacheRemoteGitBranches =
  453. getCacheRemoteGitBranches(gitRemote);
  454. Map<String, RemoteGitBranch> baseCacheRemoteGitBranchesMap =
  455. new HashMap<>();
  456. Map<String, RemoteGitBranch> timestampedCacheRemoteGitBranchMap =
  457. new HashMap<>();
  458. for (RemoteGitBranch cacheRemoteGitBranch : cacheRemoteGitBranches) {
  459. String cacheRemoteGitBranchName = cacheRemoteGitBranch.getName();
  460. if (cacheRemoteGitBranchName.matches(
  461. _cacheBranchPattern.pattern())) {
  462. if (cacheRemoteGitBranchName.matches(
  463. _cacheBranchPattern.pattern() + "-\\d+")) {
  464. timestampedCacheRemoteGitBranchMap.put(
  465. cacheRemoteGitBranchName, cacheRemoteGitBranch);
  466. }
  467. else {
  468. baseCacheRemoteGitBranchesMap.put(
  469. cacheRemoteGitBranchName, cacheRemoteGitBranch);
  470. }
  471. }
  472. }
  473. Map<String, RemoteGitBranch> orphanedBaseCacheRemoteGitBranchesMap =
  474. new HashMap<>(baseCacheRemoteGitBranchesMap);
  475. Map<String, RemoteGitBranch>
  476. orphanedTimestampedCacheRemoteGitBranchesMap = new HashMap<>(
  477. timestampedCacheRemoteGitBranchMap);
  478. for (String baseCacheRemoteGitBranchName :
  479. baseCacheRemoteGitBranchesMap.keySet()) {
  480. String timestampedCacheRemoteGitBranchNamePattern =
  481. Pattern.quote(baseCacheRemoteGitBranchName) + "-\\d+";
  482. for (String timestampedCacheRemoteGitBranchName :
  483. timestampedCacheRemoteGitBranchMap.keySet()) {
  484. if (timestampedCacheRemoteGitBranchName.matches(
  485. timestampedCacheRemoteGitBranchNamePattern)) {
  486. orphanedBaseCacheRemoteGitBranchesMap.remove(
  487. baseCacheRemoteGitBranchName);
  488. }
  489. }
  490. }
  491. for (String timestampedCacheRemoteGitBranchName :
  492. timestampedCacheRemoteGitBranchMap.keySet()) {
  493. String baseCacheRemoteGitBranchName =
  494. timestampedCacheRemoteGitBranchName.replaceAll(
  495. "(.*)-\\d+", "$1");
  496. if (baseCacheRemoteGitBranchesMap.containsKey(
  497. baseCacheRemoteGitBranchName)) {
  498. orphanedTimestampedCacheRemoteGitBranchesMap.remove(
  499. timestampedCacheRemoteGitBranchName);
  500. }
  501. }
  502. StringBuilder sb = new StringBuilder();
  503. for (String orphanedBaseCacheRemoteGitBranchName :
  504. orphanedBaseCacheRemoteGitBranchesMap.keySet()) {
  505. sb.append(orphanedBaseCacheRemoteGitBranchName);
  506. sb.append("\n");
  507. }
  508. for (String orphanedTimestampedCacheRemoteGitBranchName :
  509. orphanedTimestampedCacheRemoteGitBranchesMap.keySet()) {
  510. sb.append(orphanedTimestampedCacheRemoteGitBranchName);
  511. sb.append("\n");
  512. }
  513. System.out.println(
  514. JenkinsResultsParserUtil.combine(
  515. "Found ",
  516. String.valueOf(orphanedBaseCacheRemoteGitBranchesMap.size()),
  517. " orphaned base cache branches ", "and ",
  518. String.valueOf(
  519. orphanedTimestampedCacheRemoteGitBranchesMap.size()),
  520. " orphaned timestamp branches on ", gitRemote.getRemoteURL(),
  521. ".\n", sb.toString()));
  522. List<RemoteGitBranch> orphanedCacheRemoteGitBranches = new ArrayList<>(
  523. orphanedBaseCacheRemoteGitBranchesMap.size() +
  524. orphanedTimestampedCacheRemoteGitBranchesMap.size());
  525. orphanedCacheRemoteGitBranches.addAll(
  526. orphanedBaseCacheRemoteGitBranchesMap.values());
  527. orphanedCacheRemoteGitBranches.addAll(
  528. orphanedTimestampedCacheRemoteGitBranchesMap.values());
  529. GitWorkingDirectory gitWorkingDirectory =
  530. gitRemote.getGitWorkingDirectory();
  531. gitWorkingDirectory.deleteRemoteGitBranches(
  532. orphanedCacheRemoteGitBranches);
  533. }
  534. protected static void deleteOrphanedCacheBranches(
  535. List<GitRemote> gitRemotes) {
  536. List<Callable<Object>> callables = new ArrayList<>(gitRemotes.size());
  537. for (final GitRemote gitRemote : gitRemotes) {
  538. Callable<Object> callable = new SafeCallable<Object>() {
  539. @Override
  540. public Object safeCall() {
  541. deleteOrphanedCacheBranches(gitRemote);
  542. return null;
  543. }
  544. };
  545. callables.add(callable);
  546. }
  547. ParallelExecutor<Object> parallelExecutor = new ParallelExecutor<>(
  548. callables, _threadPoolExecutor);
  549. parallelExecutor.execute();
  550. }
  551. protected static String getCacheBranchName(
  552. String receiverUsername, String senderUsername, String senderSHA,
  553. String upstreamSHA) {
  554. return JenkinsResultsParserUtil.combine(
  555. "cache-", receiverUsername, "-", upstreamSHA, "-", senderUsername,
  556. "-", senderSHA);
  557. }
  558. protected static List<RemoteGitBranch> getCacheRemoteGitBranches(
  559. GitRemote gitRemote) {
  560. List<RemoteGitBranch> cacheRemoteGitBranches = new ArrayList<>();
  561. Set<String> lockedBaseCacheRemoteGitBranchNames = new HashSet<>();
  562. Map<String, RemoteGitBranch> remoteGitBranches = new HashMap<>();
  563. GitWorkingDirectory gitWorkingDirectory =
  564. gitRemote.getGitWorkingDirectory();
  565. for (RemoteGitBranch remoteGitBranch :
  566. gitWorkingDirectory.getRemoteGitBranches(gitRemote)) {
  567. Matcher matcher = _lockedCacheBranchPattern.matcher(
  568. remoteGitBranch.getName());
  569. if (matcher.matches()) {
  570. lockedBaseCacheRemoteGitBranchNames.add(matcher.group(1));
  571. continue;
  572. }
  573. remoteGitBranches.put(remoteGitBranch.getName(), remoteGitBranch);
  574. }
  575. for (String remoteGitBranchName :
  576. new HashSet<>(remoteGitBranches.keySet())) {
  577. for (String lockedBaseCacheRemoteGitBranchName :
  578. lockedBaseCacheRemoteGitBranchNames) {
  579. if (remoteGitBranchName.startsWith(
  580. lockedBaseCacheRemoteGitBranchName)) {
  581. remoteGitBranches.remove(remoteGitBranchName);
  582. System.out.println(
  583. JenkinsResultsParserUtil.combine(
  584. "Ignoring ", remoteGitBranchName,
  585. " because this branch is currently locked."));
  586. break;
  587. }
  588. }
  589. }
  590. for (Map.Entry<String, RemoteGitBranch> entry :
  591. remoteGitBranches.entrySet()) {
  592. String remoteGitBranchName = entry.getKey();
  593. if (remoteGitBranchName.matches(_cacheBranchPattern.pattern())) {
  594. if (hasTimestampBranch(remoteGitBranches)) {
  595. cacheRemoteGitBranches.add(entry.getValue());
  596. }
  597. else {
  598. deleteCacheRemoteGitBranch(
  599. remoteGitBranchName, gitWorkingDirectory,
  600. remoteGitBranches);
  601. }
  602. }
  603. }
  604. return cacheRemoteGitBranches;
  605. }
  606. protected static List<String> getGitHubDevNodeHostnames() {
  607. if (gitHubDevNodeHostnames != null) {
  608. return new ArrayList<>(gitHubDevNodeHostnames);
  609. }
  610. gitHubDevNodeHostnames =
  611. JenkinsResultsParserUtil.getGitHubCacheHostnames();
  612. return gitHubDevNodeHostnames;
  613. }
  614. protected static List<String> getGitHubDevRemoteURLs(
  615. GitWorkingDirectory gitWorkingDirectory) {
  616. List<String> gitHubDevRemoteURLs = new ArrayList<>();
  617. for (String gitHubDevNodeHostname : getGitHubDevNodeHostnames()) {
  618. if (gitHubDevNodeHostname.startsWith("slave-")) {
  619. gitHubDevRemoteURLs.add(
  620. JenkinsResultsParserUtil.combine(
  621. "root@", gitHubDevNodeHostname.substring(6),
  622. ":/opt/dev/projects/github/",
  623. gitWorkingDirectory.getGitRepositoryName()));
  624. continue;
  625. }
  626. gitHubDevRemoteURLs.add(
  627. JenkinsResultsParserUtil.combine(
  628. "git@", gitHubDevNodeHostname, ":",
  629. gitWorkingDirectory.getGitRepositoryUsername(), "/",
  630. gitWorkingDirectory.getGitRepositoryName(), ".git"));
  631. }
  632. return gitHubDevRemoteURLs;
  633. }
  634. protected static String getGitHubRemoteURL(
  635. String repositoryName, String userName) {
  636. return JenkinsResultsParserUtil.combine(
  637. "git@github.com:", userName, "/", repositoryName, ".git");
  638. }
  639. protected static GitRemote getRandomGitRemote(List<GitRemote> gitRemotes) {
  640. return gitRemotes.get(
  641. JenkinsResultsParserUtil.getRandomValue(0, gitRemotes.size() - 1));
  642. }
  643. protected static boolean hasTimestampBranch(
  644. Map<String, RemoteGitBranch> remoteGitBranches) {
  645. for (String remoteGitBranchName : remoteGitBranches.keySet()) {
  646. Matcher matcher = _cacheBranchPattern.matcher(remoteGitBranchName);
  647. if (matcher.matches()) {
  648. String lastBlock = matcher.group(2);
  649. if (lastBlock.matches("\\d+")) {
  650. return true;
  651. }
  652. }
  653. }
  654. return false;
  655. }
  656. protected static void pushToAllRemotes(
  657. final boolean force, final LocalGitBranch localGitBranch,
  658. final String remoteGitBranchName, final List<GitRemote> gitRemotes) {
  659. if (localGitBranch == null) {
  660. throw new RuntimeException("Local Git branch is null");
  661. }
  662. final long start = System.currentTimeMillis();
  663. List<Callable<Boolean>> callables = new ArrayList<>();
  664. for (final GitRemote gitRemote : gitRemotes) {
  665. Callable<Boolean> callable = new SafeCallable<Boolean>() {
  666. @Override
  667. public Boolean safeCall() {
  668. GitWorkingDirectory gitWorkingDirectory =
  669. gitRemote.getGitWorkingDirectory();
  670. RemoteGitBranch remoteGitBranch =
  671. gitWorkingDirectory.pushToRemoteGitRepository(
  672. force, localGitBranch, remoteGitBranchName,
  673. gitRemote);
  674. return Boolean.valueOf(remoteGitBranch != null);
  675. }
  676. };
  677. callables.add(callable);
  678. }
  679. ParallelExecutor<Boolean> parallelExecutor = new ParallelExecutor<>(
  680. callables, _threadPoolExecutor);
  681. parallelExecutor.execute();
  682. long duration = System.currentTimeMillis() - start;
  683. System.out.println(
  684. JenkinsResultsParserUtil.combine(
  685. "Pushed ", localGitBranch.getName(), " to ",
  686. remoteGitBranchName, " on ", String.valueOf(gitRemotes.size()),
  687. " git nodes in ",
  688. JenkinsResultsParserUtil.toDurationString(duration)));
  689. }
  690. protected static boolean remoteGitBranchExists(
  691. final String remoteGitBranchName,
  692. final GitWorkingDirectory gitWorkingDirectory,
  693. List<GitRemote> gitRemotes) {
  694. List<Callable<Boolean>> callables = new ArrayList<>(gitRemotes.size());
  695. for (final GitRemote gitRemote : gitRemotes) {
  696. Callable<Boolean> callable = new SafeCallable<Boolean>() {
  697. @Override
  698. public Boolean safeCall() {
  699. try {
  700. return gitWorkingDirectory.remoteGitBranchExists(
  701. remoteGitBranchName, gitRemote);
  702. }
  703. catch (Exception exception) {
  704. exception.printStackTrace();
  705. return true;
  706. }
  707. }
  708. };
  709. callables.add(callable);
  710. }
  711. ParallelExecutor<Boolean> parallelExecutor = new ParallelExecutor<>(
  712. callables, _threadPoolExecutor);
  713. for (Boolean bool : parallelExecutor.execute()) {
  714. if (!bool) {
  715. return false;
  716. }
  717. }
  718. return true;
  719. }
  720. protected static String synchronizeToGitHubDev(
  721. GitWorkingDirectory gitWorkingDirectory, String receiverUsername,
  722. int retryCount, String senderBranchName, String senderUsername,
  723. String senderBranchSHA, String upstreamBranchSHA) {
  724. long start = System.currentTimeMillis();
  725. File gitRepositoryDirectory = gitWorkingDirectory.getWorkingDirectory();
  726. LocalGitBranch currentLocalGitBranch =
  727. gitWorkingDirectory.getCurrentLocalGitBranch();
  728. if (currentLocalGitBranch == null) {
  729. LocalGitBranch localUpstreamGitBranch =
  730. gitWorkingDirectory.getUpstreamLocalGitBranch();
  731. gitWorkingDirectory.checkoutLocalGitBranch(localUpstreamGitBranch);
  732. currentLocalGitBranch = localUpstreamGitBranch;
  733. }
  734. System.out.println(
  735. JenkinsResultsParserUtil.combine(
  736. "Starting synchronization with local-git. Current repository ",
  737. "directory is ", gitRepositoryDirectory.getPath(), ". Current ",
  738. "branch is ", currentLocalGitBranch.getName(), "."));
  739. GitRemote senderGitRemote = null;
  740. try {
  741. senderGitRemote = gitWorkingDirectory.addGitRemote(
  742. true, "sender-temp",
  743. getGitHubRemoteURL(
  744. gitWorkingDirectory.getGitRepositoryName(),
  745. senderUsername));
  746. String cacheBranchName = getCacheBranchName(
  747. receiverUsername, senderUsername, senderBranchSHA,
  748. upstreamBranchSHA);
  749. String upstreamBranchName =
  750. gitWorkingDirectory.getUpstreamBranchName();
  751. List<GitRemote> gitHubDevGitRemotes = null;
  752. try {
  753. gitHubDevGitRemotes = getGitHubDevGitRemotes(
  754. gitWorkingDirectory);
  755. deleteCacheLocalGitBranches(
  756. cacheBranchName, gitWorkingDirectory);
  757. if (JenkinsResultsParserUtil.getRandomValue(1, 10) == 5) {
  758. deleteExtraTimestampBranches(gitHubDevGitRemotes);
  759. deleteOrphanedCacheBranches(gitHubDevGitRemotes);
  760. deleteExpiredRemoteGitBranches(
  761. gitWorkingDirectory, gitHubDevGitRemotes);
  762. }
  763. RemoteGitBranch cacheRemoteGitBranch = null;
  764. try {
  765. cacheRemoteGitBranch = fetchCacheBranchFromGitHubDev(
  766. gitWorkingDirectory, cacheBranchName);
  767. }
  768. catch (Exception exception) {
  769. cacheRemoteGitBranch = null;
  770. System.out.println(
  771. JenkinsResultsParserUtil.combine(
  772. "Cache branch ", cacheBranchName,
  773. " does not exist"));
  774. }
  775. if (cacheRemoteGitBranch != null) {
  776. System.out.println(
  777. JenkinsResultsParserUtil.combine(
  778. "Cache branch ", cacheBranchName,
  779. " already exists"));
  780. gitWorkingDirectory.deleteLocalGitBranch(cacheBranchName);
  781. gitWorkingDirectory.createLocalGitBranch(
  782. cacheBranchName, true, cacheRemoteGitBranch.getSHA());
  783. if (!gitWorkingDirectory.localGitBranchExists(
  784. upstreamBranchName)) {
  785. updateUpstreamLocalGitBranch(
  786. gitWorkingDirectory, upstreamBranchSHA);
  787. }
  788. updateCacheRemoteGitBranchTimestamp(
  789. cacheBranchName, gitWorkingDirectory,
  790. gitHubDevGitRemotes);
  791. return cacheBranchName;
  792. }
  793. senderBranchName = senderBranchName.trim();
  794. LocalGitBranch cacheLocalGitBranch =
  795. gitWorkingDirectory.getRebasedLocalGitBranch(
  796. cacheBranchName, senderBranchName,
  797. senderGitRemote.getRemoteURL(), senderBranchSHA,
  798. upstreamBranchName, upstreamBranchSHA);
  799. cacheBranches(
  800. gitWorkingDirectory, cacheLocalGitBranch,
  801. gitHubDevGitRemotes, "liferay");
  802. return cacheBranchName;
  803. }
  804. catch (Exception exception) {
  805. if (retryCount == 1) {
  806. throw exception;
  807. }
  808. gitHubDevGitRemotes = null;
  809. senderGitRemote = null;
  810. System.out.println(
  811. "Synchronization with local-git failed. Retrying.");
  812. exception.printStackTrace();
  813. gitWorkingDirectory.checkoutLocalGitBranch(
  814. currentLocalGitBranch);
  815. return synchronizeToGitHubDev(
  816. gitWorkingDirectory, receiverUsername, retryCount + 1,
  817. senderBranchName, senderUsername, senderBranchSHA,
  818. upstreamBranchSHA);
  819. }
  820. finally {
  821. if (gitHubDevGitRemotes != null) {
  822. try {
  823. gitWorkingDirectory.removeGitRemotes(
  824. gitHubDevGitRemotes);
  825. }
  826. catch (Exception exception) {
  827. exception.printStackTrace();
  828. }
  829. }
  830. if (gitWorkingDirectory.localGitBranchExists(
  831. currentLocalGitBranch.getName())) {
  832. gitWorkingDirectory.checkoutLocalGitBranch(
  833. currentLocalGitBranch);
  834. }
  835. else {
  836. checkoutUpstreamLocalGitBranch(
  837. gitWorkingDirectory, upstreamBranchSHA);
  838. }
  839. gitWorkingDirectory.deleteLocalGitBranch(cacheBranchName);
  840. }
  841. }
  842. finally {
  843. if (senderGitRemote != null) {
  844. try {
  845. gitWorkingDirectory.removeGitRemote(senderGitRemote);
  846. }
  847. catch (Exception exception) {
  848. exception.printStackTrace();
  849. }
  850. }
  851. String durationString = JenkinsResultsParserUtil.toDurationString(
  852. System.currentTimeMillis() - start);
  853. System.out.println(
  854. "Synchronization with local Git completed in " +
  855. durationString);
  856. }
  857. }
  858. protected static void updateCacheRemoteGitBranchTimestamp(
  859. final String cacheBranchName,
  860. final GitWorkingDirectory gitWorkingDirectory,
  861. List<GitRemote> gitHubDevGitRemotes) {
  862. long start = System.currentTimeMillis();
  863. List<RemoteGitBranch> cacheRemoteGitBranches = null;
  864. GitRemote gitHubDevGitRemote = null;
  865. while (cacheRemoteGitBranches == null) {
  866. try {
  867. gitHubDevGitRemote = getRandomGitRemote(gitHubDevGitRemotes);
  868. cacheRemoteGitBranches = getCacheRemoteGitBranches(
  869. gitHubDevGitRemote);
  870. }
  871. catch (Exception exception) {
  872. exception.printStackTrace();
  873. gitHubDevGitRemotes.remove(gitHubDevGitRemote);
  874. if (gitHubDevGitRemotes.isEmpty()) {
  875. throw new RuntimeException(
  876. "No remote repositories could be reached", exception);
  877. }
  878. }
  879. }
  880. RemoteGitBranch oldTimestampCacheRemoteGitBranch = null;
  881. Pattern pattern = Pattern.compile(
  882. Pattern.quote(cacheBranchName) + "-(\\d+)");
  883. for (RemoteGitBranch cacheRemoteGitBranch : cacheRemoteGitBranches) {
  884. Matcher matcher = pattern.matcher(cacheRemoteGitBranch.getName());
  885. if (!matcher.matches()) {
  886. continue;
  887. }
  888. long existingTimestamp = Long.parseLong(matcher.group(1));
  889. if ((System.currentTimeMillis() - existingTimestamp) >
  890. _MILLIS_BRANCH_UPDATE_AGE) {
  891. oldTimestampCacheRemoteGitBranch = cacheRemoteGitBranch;
  892. }
  893. break;
  894. }
  895. if (oldTimestampCacheRemoteGitBranch == null) {
  896. return;
  897. }
  898. String newTimestampCacheRemoteBranchName =
  899. JenkinsResultsParserUtil.combine(
  900. cacheBranchName, "-",
  901. String.valueOf(System.currentTimeMillis()));
  902. System.out.println(
  903. JenkinsResultsParserUtil.combine(
  904. "Updating existing timestamp for branch ",
  905. oldTimestampCacheRemoteGitBranch.getName(), " to ",
  906. newTimestampCacheRemoteBranchName));
  907. LocalGitBranch originalCheckedOutLocalGitBranch =
  908. gitWorkingDirectory.getCurrentLocalGitBranch();
  909. if (originalCheckedOutLocalGitBranch == null) {
  910. originalCheckedOutLocalGitBranch =
  911. gitWorkingDirectory.getUpstreamLocalGitBranch();
  912. }
  913. LocalGitBranch newTimestampLocalGitBranch =
  914. gitWorkingDirectory.createLocalGitBranch(
  915. newTimestampCacheRemoteBranchName);
  916. newTimestampLocalGitBranch = gitWorkingDirectory.fetch(
  917. newTimestampLocalGitBranch, oldTimestampCacheRemoteGitBranch);
  918. try {
  919. pushToAllRemotes(
  920. true, newTimestampLocalGitBranch,
  921. newTimestampCacheRemoteBranchName, gitHubDevGitRemotes);
  922. deleteFromAllRemotes(
  923. oldTimestampCacheRemoteGitBranch.getName(),
  924. gitHubDevGitRemotes);
  925. }
  926. finally {
  927. gitWorkingDirectory.checkoutLocalGitBranch(
  928. originalCheckedOutLocalGitBranch);
  929. gitWorkingDirectory.deleteLocalGitBranch(
  930. newTimestampLocalGitBranch);
  931. }
  932. System.out.println(
  933. JenkinsResultsParserUtil.combine(
  934. "Cache branch timestamp updated in ",
  935. JenkinsResultsParserUtil.toDurationString(
  936. System.currentTimeMillis() - start)));
  937. }
  938. protected static LocalGitBranch updateUpstreamLocalGitBranch(
  939. GitWorkingDirectory gitWorkingDirectory, String upstreamBranchSHA) {
  940. String upstreamBranchName = gitWorkingDirectory.getUpstreamBranchName();
  941. RemoteGitBranch upstreamRemoteGitBranch =
  942. gitWorkingDirectory.getRemoteGitBranch(
  943. upstreamBranchName, gitWorkingDirectory.getUpstreamGitRemote(),
  944. true);
  945. LocalGitBranch upstreamLocalGitBranch =
  946. gitWorkingDirectory.getUpstreamLocalGitBranch();
  947. if (upstreamLocalGitBranch == null) {
  948. upstreamLocalGitBranch = gitWorkingDirectory.createLocalGitBranch(
  949. upstreamBranchName);
  950. gitWorkingDirectory.fetch(
  951. upstreamLocalGitBranch, upstreamRemoteGitBranch);
  952. }
  953. String upstreamLocalGitBranchSHA = upstreamLocalGitBranch.getSHA();
  954. String upstreamRemoteGitBranchSHA = upstreamRemoteGitBranch.getSHA();
  955. if ((upstreamBranchSHA != null) &&
  956. !upstreamRemoteGitBranchSHA.equals(upstreamBranchSHA)) {
  957. upstreamRemoteGitBranchSHA = upstreamBranchSHA;
  958. }
  959. if (upstreamLocalGitBranchSHA.equals(upstreamRemoteGitBranchSHA)) {
  960. return upstreamLocalGitBranch;
  961. }
  962. gitWorkingDirectory.rebaseAbort();
  963. gitWorkingDirectory.clean();
  964. gitWorkingDirectory.reset("--hard");
  965. gitWorkingDirectory.fetch(upstreamRemoteGitBranch);
  966. String tempBranchName = "temp-" + System.currentTimeMillis();
  967. LocalGitBranch tempLocalGitBranch = null;
  968. try {
  969. tempLocalGitBranch = gitWorkingDirectory.createLocalGitBranch(
  970. tempBranchName, true, upstreamRemoteGitBranchSHA);
  971. gitWorkingDirectory.checkoutLocalGitBranch(
  972. tempLocalGitBranch, "-f");
  973. gitWorkingDirectory.deleteLocalGitBranch(upstreamBranchName);
  974. upstreamLocalGitBranch = gitWorkingDirectory.createLocalGitBranch(
  975. upstreamRemoteGitBranch.getName(), true,
  976. upstreamRemoteGitBranchSHA);
  977. gitWorkingDirectory.checkoutLocalGitBranch(upstreamLocalGitBranch);
  978. }
  979. finally {
  980. if (tempLocalGitBranch != null) {
  981. gitWorkingDirectory.deleteLocalGitBranch(tempLocalGitBranch);
  982. }
  983. }
  984. return upstreamLocalGitBranch;
  985. }
  986. protected static List<String> gitHubDevNodeHostnames;
  987. private static LocalGitBranch _createCacheLocalGitBranch(
  988. LocalGitRepository localGitRepository, String receiverUsername,
  989. String senderBranchName, String senderUsername, String senderBranchSHA,
  990. String upstreamBranchSHA, boolean synchronize) {
  991. GitWorkingDirectory gitWorkingDirectory =
  992. localGitRepository.getGitWorkingDirectory();
  993. if (!JenkinsResultsParserUtil.isCINode()) {
  994. return gitWorkingDirectory.getRebasedLocalGitBranch(
  995. JenkinsResultsParserUtil.combine(
  996. gitWorkingDirectory.getUpstreamBranchName(), "-temp-",
  997. String.valueOf(System.currentTimeMillis())),
  998. senderBranchName,
  999. JenkinsResultsParserUtil.combine(
  1000. "git@github.com:", senderUsername, "/",
  1001. localGitRepository.getName()),
  1002. senderBranchSHA, gitWorkingDirectory.getUpstreamBranchName(),
  1003. upstreamBranchSHA);
  1004. }
  1005. if (synchronize) {
  1006. synchronizeToGitHubDev(
  1007. gitWorkingDirectory, receiverUsername, 0, senderBranchName,
  1008. senderUsername, senderBranchSHA, upstreamBranchSHA);
  1009. }
  1010. String cacheBranchName = getCacheBranchName(
  1011. receiverUsername, senderUsername, senderBranchSHA,
  1012. upstreamBranchSHA);
  1013. LocalGitBranch cacheLocalGitBranch = GitBranchFactory.newLocalGitBranch(
  1014. localGitRepository,
  1015. JenkinsResultsParserUtil.combine(
  1016. gitWorkingDirectory.getUpstreamBranchName(), "-temp-",
  1017. String.valueOf(System.currentTimeMillis())),
  1018. upstreamBranchSHA);
  1019. RemoteGitBranch cacheRemoteGitBranch =
  1020. gitWorkingDirectory.getRemoteGitBranch(
  1021. cacheBranchName,
  1022. getRandomGitRemote(
  1023. getGitHubDevGitRemotes(gitWorkingDirectory)));
  1024. return gitWorkingDirectory.fetch(
  1025. cacheLocalGitBranch, cacheRemoteGitBranch);
  1026. }
  1027. private static final long _MILLIS_BRANCH_EXPIRATION =
  1028. 1000 * 60 * 60 * 24 * 2;
  1029. private static final long _MILLIS_BRANCH_UPDATE_AGE = 1000 * 60 * 60 * 24;
  1030. private static final Pattern _cacheBranchPattern = Pattern.compile(
  1031. "cache(-([^-]+))+");
  1032. private static final Pattern _lockedCacheBranchPattern = Pattern.compile(
  1033. "(cache-.*)-LOCK");
  1034. private static final ThreadPoolExecutor _threadPoolExecutor =
  1035. JenkinsResultsParserUtil.getNewThreadPoolExecutor(16, true);
  1036. private abstract static class SafeCallable<T> implements Callable<T> {
  1037. @Override
  1038. public final T call() {
  1039. try {
  1040. return safeCall();
  1041. }
  1042. catch (Exception exception) {
  1043. exception.printStackTrace();
  1044. }
  1045. return null;
  1046. }
  1047. public abstract T safeCall();
  1048. }
  1049. }