1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.internal.storage.file;
45
46 import static java.lang.Integer.valueOf;
47 import static org.junit.Assert.assertEquals;
48 import static org.junit.Assert.assertNull;
49 import static org.junit.Assert.assertSame;
50
51 import java.io.File;
52 import java.io.IOException;
53 import java.util.concurrent.BrokenBarrierException;
54 import java.util.concurrent.Callable;
55 import java.util.concurrent.CyclicBarrier;
56 import java.util.concurrent.ExecutorService;
57 import java.util.concurrent.Executors;
58 import java.util.concurrent.Future;
59 import java.util.concurrent.TimeUnit;
60
61 import org.eclipse.jgit.api.Git;
62 import org.eclipse.jgit.junit.TestRepository.BranchBuilder;
63 import org.eclipse.jgit.lib.ConfigConstants;
64 import org.eclipse.jgit.lib.Constants;
65 import org.eclipse.jgit.lib.Ref.Storage;
66 import org.eclipse.jgit.lib.RefUpdate;
67 import org.eclipse.jgit.lib.RefUpdate.Result;
68 import org.eclipse.jgit.revwalk.RevBlob;
69 import org.eclipse.jgit.revwalk.RevCommit;
70 import org.eclipse.jgit.storage.file.FileBasedConfig;
71 import org.junit.Test;
72
73 public class GcPackRefsTest extends GcTestCase {
74 @Test
75 public void looseRefPacked() throws Exception {
76 RevBlob a = tr.blob("a");
77 tr.lightweightTag("t", a);
78
79 gc.packRefs();
80 assertSame(repo.exactRef("refs/tags/t").getStorage(), Storage.PACKED);
81 }
82
83 @Test
84 public void concurrentOnlyOneWritesPackedRefs() throws Exception {
85 RevBlob a = tr.blob("a");
86 tr.lightweightTag("t", a);
87
88 final CyclicBarrier syncPoint = new CyclicBarrier(2);
89
90 Callable<Integer> packRefs = new Callable<Integer>() {
91
92
93 public Integer call() throws Exception {
94 syncPoint.await();
95 try {
96 gc.packRefs();
97 return valueOf(0);
98 } catch (IOException e) {
99 return valueOf(1);
100 }
101 }
102 };
103 ExecutorService pool = Executors.newFixedThreadPool(2);
104 try {
105 Future<Integer> p1 = pool.submit(packRefs);
106 Future<Integer> p2 = pool.submit(packRefs);
107 assertEquals(1, p1.get().intValue() + p2.get().intValue());
108 } finally {
109 pool.shutdown();
110 pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
111 }
112 }
113
114 @Test
115 public void whileRefLockedRefNotPackedNoError()
116 throws Exception {
117 RevBlob a = tr.blob("a");
118 tr.lightweightTag("t1", a);
119 tr.lightweightTag("t2", a);
120 LockFile refLock = new LockFile(new File(repo.getDirectory(),
121 "refs/tags/t1"), repo.getFS());
122 try {
123 refLock.lock();
124 gc.packRefs();
125 } finally {
126 refLock.unlock();
127 }
128
129 assertSame(repo.exactRef("refs/tags/t1").getStorage(), Storage.LOOSE);
130 assertSame(repo.exactRef("refs/tags/t2").getStorage(), Storage.PACKED);
131 }
132
133 @Test
134 public void whileRefUpdatedRefUpdateSucceeds()
135 throws Exception {
136 RevBlob a = tr.blob("a");
137 tr.lightweightTag("t", a);
138 final RevBlob b = tr.blob("b");
139
140 final CyclicBarrier refUpdateLockedRef = new CyclicBarrier(2);
141 final CyclicBarrier packRefsDone = new CyclicBarrier(2);
142 ExecutorService pool = Executors.newFixedThreadPool(2);
143 try {
144 Future<Result> result = pool.submit(new Callable<Result>() {
145
146 public Result call() throws Exception {
147 RefUpdate update = new RefDirectoryUpdate(
148 (RefDirectory) repo.getRefDatabase(),
149 repo.exactRef("refs/tags/t")) {
150 @Override
151 public boolean isForceUpdate() {
152 try {
153 refUpdateLockedRef.await();
154 packRefsDone.await();
155 } catch (InterruptedException e) {
156 Thread.currentThread().interrupt();
157 } catch (BrokenBarrierException e) {
158 Thread.currentThread().interrupt();
159 }
160 return super.isForceUpdate();
161 }
162 };
163 update.setForceUpdate(true);
164 update.setNewObjectId(b);
165 return update.update();
166 }
167 });
168
169 pool.submit(new Callable<Void>() {
170 public Void call() throws Exception {
171 refUpdateLockedRef.await();
172 gc.packRefs();
173 packRefsDone.await();
174 return null;
175 }
176 });
177
178 assertSame(result.get(), Result.FORCED);
179
180 } finally {
181 pool.shutdownNow();
182 pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
183 }
184
185 assertEquals(repo.exactRef("refs/tags/t").getObjectId(), b);
186 }
187
188 @Test
189 public void dontPackHEAD_nonBare() throws Exception {
190 BranchBuilder bb = tr.branch("refs/heads/side");
191 RevCommit first = bb.commit().add("A", "A").add("B", "B").create();
192 bb.commit().add("A", "A2").add("B", "B2").create();
193 Git git = Git.wrap(repo);
194
195
196
197 assertEquals(repo.exactRef("HEAD").getTarget().getName(),
198 "refs/heads/master");
199 assertNull(repo.exactRef("HEAD").getTarget().getObjectId());
200 gc.packRefs();
201 assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
202 assertEquals(repo.exactRef("HEAD").getTarget().getName(),
203 "refs/heads/master");
204 assertNull(repo.exactRef("HEAD").getTarget().getObjectId());
205
206 git.checkout().setName("refs/heads/side").call();
207 gc.packRefs();
208 assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
209
210
211 git.checkout().setName(first.getName()).call();
212 gc.packRefs();
213 assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
214 }
215
216 @Test
217 public void dontPackHEAD_bare() throws Exception {
218 BranchBuilder bb = tr.branch("refs/heads/side");
219 bb.commit().add("A", "A").add("B", "B").create();
220 RevCommit second = bb.commit().add("A", "A2").add("B", "B2").create();
221
222
223 FileBasedConfig cfg = repo.getConfig();
224 cfg.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
225 ConfigConstants.CONFIG_KEY_BARE, true);
226 cfg.save();
227 Git git = Git.open(repo.getDirectory());
228 repo = (FileRepository) git.getRepository();
229
230
231
232 assertEquals(repo.exactRef("HEAD").getTarget().getName(),
233 "refs/heads/master");
234 assertNull(repo.exactRef("HEAD").getTarget().getObjectId());
235 gc.packRefs();
236 assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
237 assertEquals(repo.exactRef("HEAD").getTarget().getName(),
238 "refs/heads/master");
239 assertNull(repo.exactRef("HEAD").getTarget().getObjectId());
240
241
242 repo.updateRef(Constants.HEAD).link("refs/heads/side");
243 gc.packRefs();
244 assertSame(repo.exactRef("HEAD").getStorage(), Storage.LOOSE);
245 assertEquals(repo.exactRef("HEAD").getTarget().getObjectId(),
246 second.getId());
247 }
248 }