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
345 public static Instant fsTick(File lastFile)
346 throws InterruptedException,
347 IOException {
348 File tmp;
349 FS fs = FS.DETECTED;
350 if (lastFile == null) {
351 lastFile = tmp = File
352 .createTempFile("fsTickTmpFile", null);
353 } else {
354 if (!fs.exists(lastFile)) {
355 throw new FileNotFoundException(lastFile.getPath());
356 }
357 tmp = File.createTempFile("fsTickTmpFile", null,
358 lastFile.getParentFile());
359 }
360 long res = FS.getFileStoreAttributes(tmp.toPath())
361 .getFsTimestampResolution().toNanos();
362 long sleepTime = res / 10;
363 try {
364 Instant startTime = fs.lastModifiedInstant(lastFile);
365 Instant actTime = fs.lastModifiedInstant(tmp);
366 while (actTime.compareTo(startTime) <= 0) {
367 TimeUnit.NANOSECONDS.sleep(sleepTime);
368 FileUtils.touch(tmp.toPath());
369 actTime = fs.lastModifiedInstant(tmp);
370 }
371 return actTime;
372 } finally {
373 FileUtils.delete(tmp);
374 }
375 }
376
377
378
379
380
381
382
383
384 protected void createBranch(ObjectId objectId, String branchName)
385 throws IOException {
386 RefUpdate updateRef = db.updateRef(branchName);
387 updateRef.setNewObjectId(objectId);
388 updateRef.update();
389 }
390
391
392
393
394
395
396
397 public List<Ref> getRefs() throws IOException {
398 return db.getRefDatabase().getRefs();
399 }
400
401
402
403
404
405
406
407
408 protected void checkoutBranch(String branchName)
409 throws IllegalStateException, IOException {
410 try (RevWalk walk = new RevWalk(db)) {
411 RevCommit head = walk.parseCommit(db.resolve(Constants.HEAD));
412 RevCommit branch = walk.parseCommit(db.resolve(branchName));
413 DirCacheCheckout dco = new DirCacheCheckout(db,
414 head.getTree().getId(), db.lockDirCache(),
415 branch.getTree().getId());
416 dco.setFailOnConflict(true);
417 dco.checkout();
418 }
419
420 RefUpdate refUpdate = db.updateRef(Constants.HEAD);
421 refUpdate.setRefLogMessage("checkout: moving to " + branchName, false);
422 refUpdate.link(branchName);
423 }
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441 protected File writeTrashFiles(boolean ensureDistinctTimestamps,
442 String... contents)
443 throws IOException, InterruptedException {
444 File f = null;
445 for (int i = 0; i < contents.length; i++)
446 if (contents[i] != null) {
447 if (ensureDistinctTimestamps && (f != null))
448 fsTick(f);
449 f = writeTrashFile(Integer.toString(i), contents[i]);
450 }
451 return f;
452 }
453
454
455
456
457
458
459
460
461
462
463
464
465
466 protected RevCommit commitFile(String filename, String contents, String branch) {
467 try (Git git = new Git(db)) {
468 Repository repo = git.getRepository();
469 String originalBranch = repo.getFullBranch();
470 boolean empty = repo.resolve(Constants.HEAD) == null;
471 if (!empty) {
472 if (repo.findRef(branch) == null)
473 git.branchCreate().setName(branch).call();
474 git.checkout().setName(branch).call();
475 }
476
477 writeTrashFile(filename, contents);
478 git.add().addFilepattern(filename).call();
479 RevCommit commit = git.commit()
480 .setMessage(branch + ": " + filename).call();
481
482 if (originalBranch != null)
483 git.checkout().setName(originalBranch).call();
484 else if (empty)
485 git.branchCreate().setName(branch).setStartPoint(commit).call();
486
487 return commit;
488 } catch (IOException | GitAPIException e) {
489 throw new RuntimeException(e);
490 }
491 }
492
493
494
495
496
497
498
499
500 protected DirCacheEntry createEntry(String path, FileMode mode) {
501 return createEntry(path, mode, DirCacheEntry.STAGE_0, path);
502 }
503
504
505
506
507
508
509
510
511
512 protected DirCacheEntry createEntry(final String path, final FileMode mode,
513 final String content) {
514 return createEntry(path, mode, DirCacheEntry.STAGE_0, content);
515 }
516
517
518
519
520
521
522
523
524
525
526 protected DirCacheEntry createEntry(final String path, final FileMode mode,
527 final int stage, final String content) {
528 final DirCacheEntry entry = new DirCacheEntry(path, stage);
529 entry.setFileMode(mode);
530 try (ObjectInserter.Formatter formatter = new ObjectInserter.Formatter()) {
531 entry.setObjectId(formatter.idFor(
532 Constants.OBJ_BLOB, Constants.encode(content)));
533 }
534 return entry;
535 }
536
537
538
539
540
541
542
543
544 protected DirCacheEntry createGitLink(String path, AnyObjectId objectId) {
545 final DirCacheEntry entry = new DirCacheEntry(path,
546 DirCacheEntry.STAGE_0);
547 entry.setFileMode(FileMode.GITLINK);
548 entry.setObjectId(objectId);
549 return entry;
550 }
551
552
553
554
555
556
557
558
559 public static void assertEqualsFile(File expected, File actual)
560 throws IOException {
561 assertEquals(expected.getCanonicalFile(), actual.getCanonicalFile());
562 }
563 }