1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jgit.junit;
15
16 import static java.nio.charset.StandardCharsets.UTF_8;
17 import static org.junit.Assert.assertEquals;
18
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.FileNotFoundException;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.InputStreamReader;
25 import java.io.Reader;
26 import java.nio.file.Path;
27 import java.time.Instant;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.concurrent.TimeUnit;
31
32 import org.eclipse.jgit.api.Git;
33 import org.eclipse.jgit.api.errors.GitAPIException;
34 import org.eclipse.jgit.dircache.DirCacheBuilder;
35 import org.eclipse.jgit.dircache.DirCacheCheckout;
36 import org.eclipse.jgit.dircache.DirCacheEntry;
37 import org.eclipse.jgit.internal.storage.file.FileRepository;
38 import org.eclipse.jgit.lib.AnyObjectId;
39 import org.eclipse.jgit.lib.Constants;
40 import org.eclipse.jgit.lib.FileMode;
41 import org.eclipse.jgit.lib.ObjectId;
42 import org.eclipse.jgit.lib.ObjectInserter;
43 import org.eclipse.jgit.lib.Ref;
44 import org.eclipse.jgit.lib.RefUpdate;
45 import org.eclipse.jgit.lib.Repository;
46 import org.eclipse.jgit.revwalk.RevCommit;
47 import org.eclipse.jgit.revwalk.RevWalk;
48 import org.eclipse.jgit.treewalk.FileTreeIterator;
49 import org.eclipse.jgit.util.FS;
50 import org.eclipse.jgit.util.FileUtils;
51 import org.junit.After;
52 import org.junit.Before;
53
54
55
56
57
58
59
60 public abstract class RepositoryTestCase extends LocalDiskRepositoryTestCase {
61
62
63
64
65
66
67
68 protected static void copyFile(File src, File dst)
69 throws IOException {
70 try (FileInputStream fis = new FileInputStream(src);
71 FileOutputStream fos = new FileOutputStream(dst)) {
72 final byte[] buf = new byte[4096];
73 int r;
74 while ((r = fis.read(buf)) > 0) {
75 fos.write(buf, 0, r);
76 }
77 }
78 }
79
80
81
82
83
84
85
86
87
88 protected File writeTrashFile(String name, String data)
89 throws IOException {
90 return JGitTestUtil.writeTrashFile(db, name, data);
91 }
92
93
94
95
96
97
98
99
100
101
102
103
104 protected Path writeLink(String link, String target)
105 throws Exception {
106 return JGitTestUtil.writeLink(db, link, target);
107 }
108
109
110
111
112
113
114
115
116
117
118 protected File writeTrashFile(final String subdir, final String name,
119 final String data)
120 throws IOException {
121 return JGitTestUtil.writeTrashFile(db, subdir, name, data);
122 }
123
124
125
126
127
128
129
130
131 protected String read(String name) throws IOException {
132 return JGitTestUtil.read(db, name);
133 }
134
135
136
137
138
139
140
141
142 protected boolean check(String name) {
143 return JGitTestUtil.check(db, name);
144 }
145
146
147
148
149
150
151
152
153 protected void deleteTrashFile(String name) throws IOException {
154 JGitTestUtil.deleteTrashFile(db, name);
155 }
156
157
158
159
160
161
162
163
164
165 protected static void checkFile(File f, String checkData)
166 throws IOException {
167 try (Reader r = new InputStreamReader(new FileInputStream(f),
168 UTF_8)) {
169 if (checkData.length() > 0) {
170 char[] data = new char[checkData.length()];
171 assertEquals(data.length, r.read(data));
172 assertEquals(checkData, new String(data));
173 }
174 assertEquals(-1, r.read());
175 }
176 }
177
178
179 protected FileRepository db;
180
181
182 protected File trash;
183
184
185 @Override
186 @Before
187 public void setUp() throws Exception {
188 super.setUp();
189 db = createWorkRepository();
190 trash = db.getWorkTree();
191 }
192
193 @Override
194 @After
195 public void tearDown() throws Exception {
196 db.close();
197 super.tearDown();
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235 public String indexState(int includedOptions)
236 throws IllegalStateException, IOException {
237 return indexState(db, includedOptions);
238 }
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256 protected void resetIndex(FileTreeIterator treeItr)
257 throws FileNotFoundException, IOException {
258 try (ObjectInserter inserter = db.newObjectInserter()) {
259 DirCacheBuilder builder = db.lockDirCache().builder();
260 DirCacheEntry dce;
261
262 while (!treeItr.eof()) {
263 long len = treeItr.getEntryLength();
264
265 dce = new DirCacheEntry(treeItr.getEntryPathString());
266 dce.setFileMode(treeItr.getEntryFileMode());
267 dce.setLastModified(treeItr.getEntryLastModifiedInstant());
268 dce.setLength((int) len);
269 try (FileInputStream in = new FileInputStream(
270 treeItr.getEntryFile())) {
271 dce.setObjectId(
272 inserter.insert(Constants.OBJ_BLOB, len, in));
273 }
274 builder.add(dce);
275 treeItr.next(1);
276 }
277 builder.commit();
278 inserter.flush();
279 }
280 }
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303 public static String lookup(Object l, String nameTemplate,
304 Map<Object, String> lookupTable) {
305 String name = lookupTable.get(l);
306 if (name == null) {
307 name = nameTemplate.replaceAll("%n",
308 Integer.toString(lookupTable.size()));
309 lookupTable.put(l, name);
310 }
311 return name;
312 }
313
314
315
316
317
318
319
320
321
322 public static String slashify(String str) {
323 str = str.replace('\\', '/');
324 return str;
325 }
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344 public static Instant fsTick(File lastFile)
345 throws InterruptedException,
346 IOException {
347 File tmp;
348 FS fs = FS.DETECTED;
349 if (lastFile == null) {
350 lastFile = tmp = File
351 .createTempFile("fsTickTmpFile", null);
352 } else {
353 if (!fs.exists(lastFile)) {
354 throw new FileNotFoundException(lastFile.getPath());
355 }
356 tmp = File.createTempFile("fsTickTmpFile", null,
357 lastFile.getParentFile());
358 }
359 long res = FS.getFileStoreAttributes(tmp.toPath())
360 .getFsTimestampResolution().toNanos();
361 long sleepTime = res / 10;
362 try {
363 Instant startTime = fs.lastModifiedInstant(lastFile);
364 Instant actTime = fs.lastModifiedInstant(tmp);
365 while (actTime.compareTo(startTime) <= 0) {
366 TimeUnit.NANOSECONDS.sleep(sleepTime);
367 FileUtils.touch(tmp.toPath());
368 actTime = fs.lastModifiedInstant(tmp);
369 }
370 return actTime;
371 } finally {
372 FileUtils.delete(tmp);
373 }
374 }
375
376
377
378
379
380
381
382
383 protected void createBranch(ObjectId objectId, String branchName)
384 throws IOException {
385 RefUpdate updateRef = db.updateRef(branchName);
386 updateRef.setNewObjectId(objectId);
387 updateRef.update();
388 }
389
390
391
392
393
394
395
396 public List<Ref> getRefs() throws IOException {
397 return db.getRefDatabase().getRefs();
398 }
399
400
401
402
403
404
405
406
407 protected void checkoutBranch(String branchName)
408 throws IllegalStateException, IOException {
409 try (RevWalk walk = new RevWalk(db)) {
410 RevCommit head = walk.parseCommit(db.resolve(Constants.HEAD));
411 RevCommit branch = walk.parseCommit(db.resolve(branchName));
412 DirCacheCheckout dco = new DirCacheCheckout(db,
413 head.getTree().getId(), db.lockDirCache(),
414 branch.getTree().getId());
415 dco.setFailOnConflict(true);
416 dco.checkout();
417 }
418
419 RefUpdate refUpdate = db.updateRef(Constants.HEAD);
420 refUpdate.setRefLogMessage("checkout: moving to " + branchName, false);
421 refUpdate.link(branchName);
422 }
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440 protected File writeTrashFiles(boolean ensureDistinctTimestamps,
441 String... contents)
442 throws IOException, InterruptedException {
443 File f = null;
444 for (int i = 0; i < contents.length; i++)
445 if (contents[i] != null) {
446 if (ensureDistinctTimestamps && (f != null))
447 fsTick(f);
448 f = writeTrashFile(Integer.toString(i), contents[i]);
449 }
450 return f;
451 }
452
453
454
455
456
457
458
459
460
461
462
463
464
465 protected RevCommit commitFile(String filename, String contents, String branch) {
466 try (Git git = new Git(db)) {
467 Repository repo = git.getRepository();
468 String originalBranch = repo.getFullBranch();
469 boolean empty = repo.resolve(Constants.HEAD) == null;
470 if (!empty) {
471 if (repo.findRef(branch) == null)
472 git.branchCreate().setName(branch).call();
473 git.checkout().setName(branch).call();
474 }
475
476 writeTrashFile(filename, contents);
477 git.add().addFilepattern(filename).call();
478 RevCommit commit = git.commit()
479 .setMessage(branch + ": " + filename).call();
480
481 if (originalBranch != null)
482 git.checkout().setName(originalBranch).call();
483 else if (empty)
484 git.branchCreate().setName(branch).setStartPoint(commit).call();
485
486 return commit;
487 } catch (IOException | GitAPIException e) {
488 throw new RuntimeException(e);
489 }
490 }
491
492
493
494
495
496
497
498
499 protected DirCacheEntry createEntry(String path, FileMode mode) {
500 return createEntry(path, mode, DirCacheEntry.STAGE_0, path);
501 }
502
503
504
505
506
507
508
509
510
511 protected DirCacheEntry createEntry(final String path, final FileMode mode,
512 final String content) {
513 return createEntry(path, mode, DirCacheEntry.STAGE_0, content);
514 }
515
516
517
518
519
520
521
522
523
524
525 protected DirCacheEntry createEntry(final String path, final FileMode mode,
526 final int stage, final String content) {
527 final DirCacheEntry entry = new DirCacheEntry(path, stage);
528 entry.setFileMode(mode);
529 try (ObjectInserter.Formatter formatter = new ObjectInserter.Formatter()) {
530 entry.setObjectId(formatter.idFor(
531 Constants.OBJ_BLOB, Constants.encode(content)));
532 }
533 return entry;
534 }
535
536
537
538
539
540
541
542
543 protected DirCacheEntry createGitLink(String path, AnyObjectId objectId) {
544 final DirCacheEntry entry = new DirCacheEntry(path,
545 DirCacheEntry.STAGE_0);
546 entry.setFileMode(FileMode.GITLINK);
547 entry.setObjectId(objectId);
548 return entry;
549 }
550
551
552
553
554
555
556
557
558 public static void assertEqualsFile(File expected, File actual)
559 throws IOException {
560 assertEquals(expected.getCanonicalFile(), actual.getCanonicalFile());
561 }
562 }