Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

GcPackRefsTest.java 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * Copyright (C) 2012, Christian Halstrick <christian.halstrick@sap.com> and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.internal.storage.file;
  11. import static org.hamcrest.MatcherAssert.assertThat;
  12. import static org.hamcrest.Matchers.lessThanOrEqualTo;
  13. import static org.junit.Assert.assertEquals;
  14. import static org.junit.Assert.assertFalse;
  15. import static org.junit.Assert.assertNotNull;
  16. import static org.junit.Assert.assertNull;
  17. import static org.junit.Assert.assertSame;
  18. import java.io.File;
  19. import java.io.IOException;
  20. import java.nio.file.Files;
  21. import java.nio.file.Path;
  22. import java.util.concurrent.BrokenBarrierException;
  23. import java.util.concurrent.Callable;
  24. import java.util.concurrent.CyclicBarrier;
  25. import java.util.concurrent.ExecutorService;
  26. import java.util.concurrent.Executors;
  27. import java.util.concurrent.Future;
  28. import java.util.concurrent.TimeUnit;
  29. import org.eclipse.jgit.api.Git;
  30. import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
  31. import org.eclipse.jgit.lib.ConfigConstants;
  32. import org.eclipse.jgit.lib.Constants;
  33. import org.eclipse.jgit.lib.Ref.Storage;
  34. import org.eclipse.jgit.lib.RefUpdate;
  35. import org.eclipse.jgit.lib.RefUpdate.Result;
  36. import org.eclipse.jgit.revwalk.RevBlob;
  37. import org.eclipse.jgit.revwalk.RevCommit;
  38. import org.eclipse.jgit.storage.file.FileBasedConfig;
  39. import org.junit.Test;
  40. @SuppressWarnings("boxing")
  41. public class GcPackRefsTest extends GcTestCase {
  42. @Test
  43. public void looseRefPacked() throws Exception {
  44. RevBlob a = tr.blob("a");
  45. tr.lightweightTag("t", a);
  46. gc.packRefs();
  47. assertSame(repo.exactRef("refs/tags/t").getStorage(), Storage.PACKED);
  48. }
  49. @Test
  50. public void emptyRefDirectoryDeleted() throws Exception {
  51. String ref = "dir/ref";
  52. tr.branch(ref).commit().create();
  53. String name = repo.findRef(ref).getName();
  54. Path dir = repo.getDirectory().toPath().resolve(name).getParent();
  55. assertNotNull(dir);
  56. gc.packRefs();
  57. assertFalse(Files.exists(dir));
  58. }
  59. @Test
  60. public void concurrentOnlyOneWritesPackedRefs() throws Exception {
  61. RevBlob a = tr.blob("a");
  62. tr.lightweightTag("t", a);
  63. CyclicBarrier syncPoint = new CyclicBarrier(2);
  64. // Returns 0 for success, 1 in case of error when writing pack.
  65. Callable<Integer> packRefs = () -> {
  66. syncPoint.await();
  67. try {
  68. gc.packRefs();
  69. return 0;
  70. } catch (IOException e) {
  71. return 1;
  72. }
  73. };
  74. ExecutorService pool = Executors.newFixedThreadPool(2);
  75. try {
  76. Future<Integer> p1 = pool.submit(packRefs);
  77. Future<Integer> p2 = pool.submit(packRefs);
  78. assertThat(p1.get() + p2.get(), lessThanOrEqualTo(1));
  79. } finally {
  80. pool.shutdown();
  81. pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
  82. }
  83. }
  84. @Test
  85. public void whileRefLockedRefNotPackedNoError()
  86. throws Exception {
  87. RevBlob a = tr.blob("a");
  88. tr.lightweightTag("t1", a);
  89. tr.lightweightTag("t2", a);
  90. LockFile refLock = new LockFile(new File(repo.getDirectory(),
  91. "refs/tags/t1"));
  92. try {
  93. refLock.lock();
  94. gc.packRefs();
  95. } finally {
  96. refLock.unlock();
  97. }
  98. assertSame(repo.exactRef("refs/tags/t1").getStorage(), Storage.LOOSE);
  99. assertSame(repo.exactRef("refs/tags/t2").getStorage(), Storage.PACKED);
  100. }
  101. @Test
  102. public void whileRefUpdatedRefUpdateSucceeds()
  103. throws Exception {
  104. RevBlob a = tr.blob("a");
  105. tr.lightweightTag("t", a);
  106. final RevBlob b = tr.blob("b");
  107. final CyclicBarrier refUpdateLockedRef = new CyclicBarrier(2);
  108. final CyclicBarrier packRefsDone = new CyclicBarrier(2);
  109. ExecutorService pool = Executors.newFixedThreadPool(2);
  110. try {
  111. Future<Result> result = pool.submit(() -> {
  112. RefUpdate update = new RefDirectoryUpdate(
  113. (RefDirectory) repo.getRefDatabase(),
  114. repo.exactRef("refs/tags/t")) {
  115. @Override
  116. public boolean isForceUpdate() {
  117. try {
  118. refUpdateLockedRef.await();
  119. packRefsDone.await();
  120. } catch (InterruptedException
  121. | BrokenBarrierException e) {
  122. Thread.currentThread().interrupt();
  123. }
  124. return super.isForceUpdate();
  125. }
  126. };
  127. update.setForceUpdate(true);
  128. update.setNewObjectId(b);
  129. return update.update();
  130. });
  131. Future<Result> result2 = pool.submit(() -> {
  132. refUpdateLockedRef.await();
  133. gc.packRefs();
  134. packRefsDone.await();
  135. return null;
  136. });
  137. assertNull(result2.get());
  138. assertSame(result.get(), Result.FORCED);
  139. } finally {
  140. pool.shutdownNow();
  141. pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
  142. }
  143. assertEquals(repo.exactRef("refs/tags/t").getObjectId(), b);
  144. }
  145. @Test
  146. public void dontPackHEAD_nonBare() throws Exception {
  147. BranchBuilder bb = tr.branch("refs/heads/side");
  148. RevCommit first = bb.commit().add("A", "A").add("B", "B").create();
  149. bb.commit().add("A", "A2").add("B", "B2").create();
  150. Git git = Git.wrap(repo);
  151. // check for the unborn branch master. HEAD should point to master and
  152. // master doesn't exist.
  153. assertEquals(repo.exactRef("HEAD").getTarget().getName(),
  154. "refs/heads/master");
  155. assertNull(repo.exactRef("HEAD").getTarget().getObjectId());
  156. gc.packRefs();
  157. assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
  158. assertEquals(repo.exactRef("HEAD").getTarget().getName(),
  159. "refs/heads/master");
  160. assertNull(repo.exactRef("HEAD").getTarget().getObjectId());
  161. git.checkout().setName("refs/heads/side").call();
  162. gc.packRefs();
  163. assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
  164. // check for detached HEAD
  165. git.checkout().setName(first.getName()).call();
  166. gc.packRefs();
  167. assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
  168. }
  169. @Test
  170. public void dontPackHEAD_bare() throws Exception {
  171. BranchBuilder bb = tr.branch("refs/heads/side");
  172. bb.commit().add("A", "A").add("B", "B").create();
  173. RevCommit second = bb.commit().add("A", "A2").add("B", "B2").create();
  174. // Convert the repo to be bare
  175. FileBasedConfig cfg = repo.getConfig();
  176. cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
  177. ConfigConstants.CONFIG_KEY_BARE, true);
  178. cfg.save();
  179. Git git = Git.open(repo.getDirectory());
  180. repo = (FileRepository) git.getRepository();
  181. // check for the unborn branch master. HEAD should point to master and
  182. // master doesn't exist.
  183. assertEquals(repo.exactRef("HEAD").getTarget().getName(),
  184. "refs/heads/master");
  185. assertNull(repo.exactRef("HEAD").getTarget().getObjectId());
  186. gc.packRefs();
  187. assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
  188. assertEquals(repo.exactRef("HEAD").getTarget().getName(),
  189. "refs/heads/master");
  190. assertNull(repo.exactRef("HEAD").getTarget().getObjectId());
  191. // check for non-detached HEAD
  192. repo.updateRef(Constants.HEAD).link("refs/heads/side");
  193. gc.packRefs();
  194. assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
  195. assertEquals(repo.exactRef("HEAD").getTarget().getObjectId(),
  196. second.getId());
  197. }
  198. }