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.junit;
45
46 import static java.nio.charset.StandardCharsets.UTF_8;
47 import static org.junit.Assert.assertEquals;
48 import static org.junit.Assert.fail;
49
50 import java.io.BufferedOutputStream;
51 import java.io.File;
52 import java.io.FileOutputStream;
53 import java.io.IOException;
54 import java.io.OutputStream;
55 import java.security.MessageDigest;
56 import java.util.ArrayList;
57 import java.util.Arrays;
58 import java.util.Collections;
59 import java.util.Date;
60 import java.util.HashSet;
61 import java.util.List;
62 import java.util.Set;
63 import java.util.TimeZone;
64
65 import org.eclipse.jgit.api.Git;
66 import org.eclipse.jgit.dircache.DirCache;
67 import org.eclipse.jgit.dircache.DirCacheBuilder;
68 import org.eclipse.jgit.dircache.DirCacheEditor;
69 import org.eclipse.jgit.dircache.DirCacheEditor.DeletePath;
70 import org.eclipse.jgit.dircache.DirCacheEditor.DeleteTree;
71 import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
72 import org.eclipse.jgit.dircache.DirCacheEntry;
73 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
74 import org.eclipse.jgit.errors.MissingObjectException;
75 import org.eclipse.jgit.errors.ObjectWritingException;
76 import org.eclipse.jgit.internal.storage.file.FileRepository;
77 import org.eclipse.jgit.internal.storage.file.LockFile;
78 import org.eclipse.jgit.internal.storage.file.ObjectDirectory;
79 import org.eclipse.jgit.internal.storage.file.PackFile;
80 import org.eclipse.jgit.internal.storage.file.PackIndex.MutableEntry;
81 import org.eclipse.jgit.internal.storage.pack.PackWriter;
82 import org.eclipse.jgit.lib.AnyObjectId;
83 import org.eclipse.jgit.lib.Constants;
84 import org.eclipse.jgit.lib.FileMode;
85 import org.eclipse.jgit.lib.NullProgressMonitor;
86 import org.eclipse.jgit.lib.ObjectChecker;
87 import org.eclipse.jgit.lib.ObjectId;
88 import org.eclipse.jgit.lib.ObjectInserter;
89 import org.eclipse.jgit.lib.PersonIdent;
90 import org.eclipse.jgit.lib.Ref;
91 import org.eclipse.jgit.lib.RefUpdate;
92 import org.eclipse.jgit.lib.RefWriter;
93 import org.eclipse.jgit.lib.Repository;
94 import org.eclipse.jgit.lib.TagBuilder;
95 import org.eclipse.jgit.merge.MergeStrategy;
96 import org.eclipse.jgit.merge.ThreeWayMerger;
97 import org.eclipse.jgit.revwalk.ObjectWalk;
98 import org.eclipse.jgit.revwalk.RevBlob;
99 import org.eclipse.jgit.revwalk.RevCommit;
100 import org.eclipse.jgit.revwalk.RevObject;
101 import org.eclipse.jgit.revwalk.RevTag;
102 import org.eclipse.jgit.revwalk.RevTree;
103 import org.eclipse.jgit.revwalk.RevWalk;
104 import org.eclipse.jgit.treewalk.TreeWalk;
105 import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
106 import org.eclipse.jgit.util.ChangeIdUtil;
107 import org.eclipse.jgit.util.FileUtils;
108
109
110
111
112
113
114
115 public class TestRepository<R extends Repository> {
116
117
118 public static final String AUTHOR = "J. Author";
119
120
121 public static final String AUTHOR_EMAIL = "jauthor@example.com";
122
123
124 public static final String COMMITTER = "J. Committer";
125
126
127 public static final String COMMITTER_EMAIL = "jcommitter@example.com";
128
129 private final PersonIdent defaultAuthor;
130
131 private final PersonIdent defaultCommitter;
132
133 private final R db;
134
135 private final Git git;
136
137 private final RevWalk pool;
138
139 private final ObjectInserter inserter;
140
141 private final MockSystemReader mockSystemReader;
142
143
144
145
146
147
148
149
150 public TestRepository(R db) throws IOException {
151 this(db, new RevWalk(db), new MockSystemReader());
152 }
153
154
155
156
157
158
159
160
161
162
163 public TestRepository(R db, RevWalk rw) throws IOException {
164 this(db, rw, new MockSystemReader());
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 public TestRepository(R db, RevWalk rw, MockSystemReader reader)
181 throws IOException {
182 this.db = db;
183 this.git = Git.wrap(db);
184 this.pool = rw;
185 this.inserter = db.newObjectInserter();
186 this.mockSystemReader = reader;
187 long now = mockSystemReader.getCurrentTime();
188 int tz = mockSystemReader.getTimezone(now);
189 defaultAuthor = new PersonIdent(AUTHOR, AUTHOR_EMAIL, now, tz);
190 defaultCommitter = new PersonIdent(COMMITTER, COMMITTER_EMAIL, now, tz);
191 }
192
193
194
195
196
197
198 public R getRepository() {
199 return db;
200 }
201
202
203
204
205
206
207 public RevWalk getRevWalk() {
208 return pool;
209 }
210
211
212
213
214
215
216
217
218 public Git git() {
219 return git;
220 }
221
222
223
224
225
226
227
228 public Date getDate() {
229 return new Date(mockSystemReader.getCurrentTime());
230 }
231
232
233
234
235
236
237 public TimeZone getTimeZone() {
238 return mockSystemReader.getTimeZone();
239 }
240
241
242
243
244
245
246
247 public void tick(int secDelta) {
248 mockSystemReader.tick(secDelta);
249 }
250
251
252
253
254
255
256
257 public void setAuthorAndCommitter(org.eclipse.jgit.lib.CommitBuilder c) {
258 c.setAuthor(new PersonIdent(defaultAuthor, getDate()));
259 c.setCommitter(new PersonIdent(defaultCommitter, getDate()));
260 }
261
262
263
264
265
266
267
268
269
270 public RevBlob blob(String content) throws Exception {
271 return blob(content.getBytes(UTF_8));
272 }
273
274
275
276
277
278
279
280
281
282 public RevBlob blob(byte[] content) throws Exception {
283 ObjectId id;
284 try (ObjectInserter ins = inserter) {
285 id = ins.insert(Constants.OBJ_BLOB, content);
286 ins.flush();
287 }
288 return (RevBlob) pool.parseAny(id);
289 }
290
291
292
293
294
295
296
297
298
299
300
301 public DirCacheEntry file(String path, RevBlob blob)
302 throws Exception {
303 final DirCacheEntry e = new DirCacheEntry(path);
304 e.setFileMode(FileMode.REGULAR_FILE);
305 e.setObjectId(blob);
306 return e;
307 }
308
309
310
311
312
313
314
315
316
317
318 public RevTree tree(DirCacheEntry... entries) throws Exception {
319 final DirCache dc = DirCache.newInCore();
320 final DirCacheBuilder b = dc.builder();
321 for (DirCacheEntry e : entries) {
322 b.add(e);
323 }
324 b.finish();
325 ObjectId root;
326 try (ObjectInserter ins = inserter) {
327 root = dc.writeTree(ins);
328 ins.flush();
329 }
330 return pool.parseTree(root);
331 }
332
333
334
335
336
337
338
339
340
341
342
343 public RevObject get(RevTree tree, String path)
344 throws Exception {
345 try (TreeWalk tw = new TreeWalk(pool.getObjectReader())) {
346 tw.setFilter(PathFilterGroup.createFromStrings(Collections
347 .singleton(path)));
348 tw.reset(tree);
349 while (tw.next()) {
350 if (tw.isSubtree() && !path.equals(tw.getPathString())) {
351 tw.enterSubtree();
352 continue;
353 }
354 final ObjectId entid = tw.getObjectId(0);
355 final FileMode entmode = tw.getFileMode(0);
356 return pool.lookupAny(entid, entmode.getObjectType());
357 }
358 }
359 fail("Can't find " + path + " in tree " + tree.name());
360 return null;
361 }
362
363
364
365
366
367
368
369
370
371
372
373
374 public RevCommit commit(RevCommit... parents) throws Exception {
375 return commit(1, tree(), parents);
376 }
377
378
379
380
381
382
383
384
385
386
387
388
389
390 public RevCommit commit(RevTree tree, RevCommit... parents)
391 throws Exception {
392 return commit(1, tree, parents);
393 }
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408 public RevCommit commit(int secDelta, RevCommit... parents)
409 throws Exception {
410 return commit(secDelta, tree(), parents);
411 }
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429 public RevCommit commit(final int secDelta, final RevTree tree,
430 final RevCommit... parents) throws Exception {
431 tick(secDelta);
432
433 final org.eclipse.jgit.lib.CommitBuilder c;
434
435 c = new org.eclipse.jgit.lib.CommitBuilder();
436 c.setTreeId(tree);
437 c.setParentIds(parents);
438 c.setAuthor(new PersonIdent(defaultAuthor, getDate()));
439 c.setCommitter(new PersonIdent(defaultCommitter, getDate()));
440 c.setMessage("");
441 ObjectId id;
442 try (ObjectInserter ins = inserter) {
443 id = ins.insert(c);
444 ins.flush();
445 }
446 return pool.parseCommit(id);
447 }
448
449
450
451
452
453
454 public CommitBuilder commit() {
455 return new CommitBuilder();
456 }
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474 public RevTag tag(String name, RevObject dst) throws Exception {
475 final TagBuilder t = new TagBuilder();
476 t.setObjectId(dst);
477 t.setTag(name);
478 t.setTagger(new PersonIdent(defaultCommitter, getDate()));
479 t.setMessage("");
480 ObjectId id;
481 try (ObjectInserter ins = inserter) {
482 id = ins.insert(t);
483 ins.flush();
484 }
485 return pool.parseTag(id);
486 }
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502 public RevCommit update(String ref, CommitBuilder to) throws Exception {
503 return update(ref, to.create());
504 }
505
506
507
508
509
510
511
512
513
514
515
516
517
518 public CommitBuilder amendRef(String ref) throws Exception {
519 String name = normalizeRef(ref);
520 Ref r = db.exactRef(name);
521 if (r == null)
522 throw new IOException("Not a ref: " + ref);
523 return amend(pool.parseCommit(r.getObjectId()), branch(name).commit());
524 }
525
526
527
528
529
530
531
532
533
534 public CommitBuilder amend(AnyObjectId id) throws Exception {
535 return amend(pool.parseCommit(id), commit());
536 }
537
538 private CommitBuilder amend(RevCommit old, CommitBuilder b) throws Exception {
539 pool.parseBody(old);
540 b.author(old.getAuthorIdent());
541 b.committer(old.getCommitterIdent());
542 b.message(old.getFullMessage());
543
544
545 b.updateCommitterTime = true;
546
547
548 b.noParents();
549 for (int i = 0; i < old.getParentCount(); i++)
550 b.parent(old.getParent(i));
551
552
553
554 b.tree.clear();
555 try (TreeWalk tw = new TreeWalk(db)) {
556 tw.reset(old.getTree());
557 tw.setRecursive(true);
558 while (tw.next()) {
559 b.edit(new PathEdit(tw.getPathString()) {
560 @Override
561 public void apply(DirCacheEntry ent) {
562 ent.setFileMode(tw.getFileMode(0));
563 ent.setObjectId(tw.getObjectId(0));
564 }
565 });
566 }
567 }
568
569 return b;
570 }
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588 public <T extends AnyObjectId> T update(String ref, T obj) throws Exception {
589 ref = normalizeRef(ref);
590 RefUpdate u = db.updateRef(ref);
591 u.setNewObjectId(obj);
592 switch (u.forceUpdate()) {
593 case FAST_FORWARD:
594 case FORCED:
595 case NEW:
596 case NO_CHANGE:
597 updateServerInfo();
598 return obj;
599
600 default:
601 throw new IOException("Cannot write " + ref + " " + u.getResult());
602 }
603 }
604
605
606
607
608
609
610
611
612
613
614 public void delete(String ref) throws Exception {
615 ref = normalizeRef(ref);
616 RefUpdate u = db.updateRef(ref);
617 u.setForceUpdate(true);
618 switch (u.delete()) {
619 case FAST_FORWARD:
620 case FORCED:
621 case NEW:
622 case NO_CHANGE:
623 updateServerInfo();
624 return;
625
626 default:
627 throw new IOException("Cannot delete " + ref + " " + u.getResult());
628 }
629 }
630
631 private static String normalizeRef(String ref) {
632 if (Constants.HEAD.equals(ref)) {
633
634 } else if ("FETCH_HEAD".equals(ref)) {
635
636 } else if ("MERGE_HEAD".equals(ref)) {
637
638 } else if (ref.startsWith(Constants.R_REFS)) {
639
640 } else
641 ref = Constants.R_HEADS + ref;
642 return ref;
643 }
644
645
646
647
648
649
650
651
652
653 public void reset(AnyObjectId id) throws Exception {
654 RefUpdate ru = db.updateRef(Constants.HEAD, true);
655 ru.setNewObjectId(id);
656 RefUpdate.Result result = ru.forceUpdate();
657 switch (result) {
658 case FAST_FORWARD:
659 case FORCED:
660 case NEW:
661 case NO_CHANGE:
662 break;
663 default:
664 throw new IOException(String.format(
665 "Checkout \"%s\" failed: %s", id.name(), result));
666 }
667 }
668
669
670
671
672
673
674
675
676
677
678
679
680 public void reset(String name) throws Exception {
681 RefUpdate.Result result;
682 ObjectId id = db.resolve(name);
683 if (id == null)
684 throw new IOException("Not a revision: " + name);
685 RefUpdate ru = db.updateRef(Constants.HEAD, false);
686 ru.setNewObjectId(id);
687 result = ru.forceUpdate();
688 switch (result) {
689 case FAST_FORWARD:
690 case FORCED:
691 case NEW:
692 case NO_CHANGE:
693 break;
694 default:
695 throw new IOException(String.format(
696 "Checkout \"%s\" failed: %s", name, result));
697 }
698 }
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713 public RevCommit cherryPick(AnyObjectId id) throws Exception {
714 RevCommit commit = pool.parseCommit(id);
715 pool.parseBody(commit);
716 if (commit.getParentCount() != 1)
717 throw new IOException(String.format(
718 "Expected 1 parent for %s, found: %s",
719 id.name(), Arrays.asList(commit.getParents())));
720 RevCommit parent = commit.getParent(0);
721 pool.parseHeaders(parent);
722
723 Ref headRef = db.exactRef(Constants.HEAD);
724 if (headRef == null)
725 throw new IOException("Missing HEAD");
726 RevCommit head = pool.parseCommit(headRef.getObjectId());
727
728 ThreeWayMerger merger = MergeStrategy.RECURSIVE.newMerger(db, true);
729 merger.setBase(parent.getTree());
730 if (merger.merge(head, commit)) {
731 if (AnyObjectId.equals(head.getTree(), merger.getResultTreeId()))
732 return null;
733 tick(1);
734 org.eclipse.jgit.lib.CommitBuilder b =
735 new org.eclipse.jgit.lib.CommitBuilder();
736 b.setParentId(head);
737 b.setTreeId(merger.getResultTreeId());
738 b.setAuthor(commit.getAuthorIdent());
739 b.setCommitter(new PersonIdent(defaultCommitter, getDate()));
740 b.setMessage(commit.getFullMessage());
741 ObjectId result;
742 try (ObjectInserter ins = inserter) {
743 result = ins.insert(b);
744 ins.flush();
745 }
746 update(Constants.HEAD, result);
747 return pool.parseCommit(result);
748 } else {
749 throw new IOException("Merge conflict");
750 }
751 }
752
753
754
755
756
757
758 public void updateServerInfo() throws Exception {
759 if (db instanceof FileRepository) {
760 final FileRepository fr = (FileRepository) db;
761 RefWriter rw = new RefWriter(fr.getRefDatabase().getRefs()) {
762 @Override
763 protected void writeFile(String name, byte[] bin)
764 throws IOException {
765 File path = new File(fr.getDirectory(), name);
766 TestRepository.this.writeFile(path, bin);
767 }
768 };
769 rw.writePackedRefs();
770 rw.writeInfoRefs();
771
772 final StringBuilder w = new StringBuilder();
773 for (PackFile p : fr.getObjectDatabase().getPacks()) {
774 w.append("P ");
775 w.append(p.getPackFile().getName());
776 w.append('\n');
777 }
778 writeFile(new File(new File(fr.getObjectDatabase().getDirectory(),
779 "info"), "packs"), Constants.encodeASCII(w.toString()));
780 }
781 }
782
783
784
785
786
787
788
789
790
791
792
793
794
795 public <T extends RevObject> T parseBody(T object) throws Exception {
796 pool.parseBody(object);
797 return object;
798 }
799
800
801
802
803
804
805
806
807
808
809 public BranchBuilder branch(String ref) {
810 if (Constants.HEAD.equals(ref)) {
811
812 } else if (ref.startsWith(Constants.R_REFS)) {
813
814 } else
815 ref = Constants.R_HEADS + ref;
816 return new BranchBuilder(ref);
817 }
818
819
820
821
822
823
824
825
826
827
828
829
830 public ObjectId lightweightTag(String name, ObjectId obj) throws Exception {
831 if (!name.startsWith(Constants.R_TAGS))
832 name = Constants.R_TAGS + name;
833 return update(name, obj);
834 }
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849 public void fsck(RevObject... tips) throws MissingObjectException,
850 IncorrectObjectTypeException, IOException {
851 try (ObjectWalk ow = new ObjectWalk(db)) {
852 if (tips.length != 0) {
853 for (RevObject o : tips)
854 ow.markStart(ow.parseAny(o));
855 } else {
856 for (Ref r : db.getRefDatabase().getRefs())
857 ow.markStart(ow.parseAny(r.getObjectId()));
858 }
859
860 ObjectChecker oc = new ObjectChecker();
861 for (;;) {
862 final RevCommit o = ow.next();
863 if (o == null)
864 break;
865
866 final byte[] bin = db.open(o, o.getType()).getCachedBytes();
867 oc.checkCommit(o, bin);
868 assertHash(o, bin);
869 }
870
871 for (;;) {
872 final RevObject o = ow.nextObject();
873 if (o == null)
874 break;
875
876 final byte[] bin = db.open(o, o.getType()).getCachedBytes();
877 oc.check(o, o.getType(), bin);
878 assertHash(o, bin);
879 }
880 }
881 }
882
883 private static void assertHash(RevObject id, byte[] bin) {
884 MessageDigest md = Constants.newMessageDigest();
885 md.update(Constants.encodedTypeString(id.getType()));
886 md.update((byte) ' ');
887 md.update(Constants.encodeASCII(bin.length));
888 md.update((byte) 0);
889 md.update(bin);
890 assertEquals(id, ObjectId.fromRaw(md.digest()));
891 }
892
893
894
895
896
897
898
899
900
901 public void packAndPrune() throws Exception {
902 if (db.getObjectDatabase() instanceof ObjectDirectory) {
903 ObjectDirectory odb = (ObjectDirectory) db.getObjectDatabase();
904 NullProgressMonitor m = NullProgressMonitor.INSTANCE;
905
906 final File pack, idx;
907 try (PackWriter pw = new PackWriter(db)) {
908 Set<ObjectId> all = new HashSet<>();
909 for (Ref r : db.getRefDatabase().getRefs())
910 all.add(r.getObjectId());
911 pw.preparePack(m, all, PackWriter.NONE);
912
913 final ObjectId name = pw.computeName();
914
915 pack = nameFor(odb, name, ".pack");
916 try (OutputStream out =
917 new BufferedOutputStream(new FileOutputStream(pack))) {
918 pw.writePack(m, m, out);
919 }
920 pack.setReadOnly();
921
922 idx = nameFor(odb, name, ".idx");
923 try (OutputStream out =
924 new BufferedOutputStream(new FileOutputStream(idx))) {
925 pw.writeIndex(out);
926 }
927 idx.setReadOnly();
928 }
929
930 odb.openPack(pack);
931 updateServerInfo();
932 prunePacked(odb);
933 }
934 }
935
936 private static void prunePacked(ObjectDirectory odb) throws IOException {
937 for (PackFile p : odb.getPacks()) {
938 for (MutableEntry e : p)
939 FileUtils.delete(odb.fileFor(e.toObjectId()));
940 }
941 }
942
943 private static File nameFor(ObjectDirectory odb, ObjectId name, String t) {
944 File packdir = odb.getPackDirectory();
945 return new File(packdir, "pack-" + name.name() + t);
946 }
947
948 private void writeFile(File p, byte[] bin) throws IOException,
949 ObjectWritingException {
950 final LockFile lck = new LockFile(p);
951 if (!lck.lock())
952 throw new ObjectWritingException("Can't write " + p);
953 try {
954 lck.write(bin);
955 } catch (IOException ioe) {
956 throw new ObjectWritingException("Can't write " + p);
957 }
958 if (!lck.commit())
959 throw new ObjectWritingException("Can't write " + p);
960 }
961
962
963 public class BranchBuilder {
964 private final String ref;
965
966 BranchBuilder(String ref) {
967 this.ref = ref;
968 }
969
970
971
972
973
974
975
976
977
978 public CommitBuilder commit() throws Exception {
979 return new CommitBuilder(this);
980 }
981
982
983
984
985
986
987
988
989
990 public RevCommit update(CommitBuilder to) throws Exception {
991 return update(to.create());
992 }
993
994
995
996
997
998
999
1000
1001
1002 public RevCommit update(RevCommit to) throws Exception {
1003 return TestRepository.this.update(ref, to);
1004 }
1005
1006
1007
1008
1009
1010
1011 public void delete() throws Exception {
1012 TestRepository.this.delete(ref);
1013 }
1014 }
1015
1016
1017 public class CommitBuilder {
1018 private final BranchBuilder branch;
1019
1020 private final DirCache tree = DirCache.newInCore();
1021
1022 private ObjectId topLevelTree;
1023
1024 private final List<RevCommit> parents = new ArrayList<>(2);
1025
1026 private int tick = 1;
1027
1028 private String message = "";
1029
1030 private RevCommit self;
1031
1032 private PersonIdent author;
1033 private PersonIdent committer;
1034
1035 private String changeId;
1036
1037 private boolean updateCommitterTime;
1038
1039 CommitBuilder() {
1040 branch = null;
1041 }
1042
1043 CommitBuilder(BranchBuilder b) throws Exception {
1044 branch = b;
1045
1046 Ref ref = db.exactRef(branch.ref);
1047 if (ref != null && ref.getObjectId() != null)
1048 parent(pool.parseCommit(ref.getObjectId()));
1049 }
1050
1051 CommitBuilder(CommitBuilder prior) throws Exception {
1052 branch = prior.branch;
1053
1054 DirCacheBuilder b = tree.builder();
1055 for (int i = 0; i < prior.tree.getEntryCount(); i++)
1056 b.add(prior.tree.getEntry(i));
1057 b.finish();
1058
1059 parents.add(prior.create());
1060 }
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070 public CommitBuilder parent(RevCommit p) throws Exception {
1071 if (parents.isEmpty()) {
1072 DirCacheBuilder b = tree.builder();
1073 parseBody(p);
1074 b.addTree(new byte[0], DirCacheEntry.STAGE_0, pool
1075 .getObjectReader(), p.getTree());
1076 b.finish();
1077 }
1078 parents.add(p);
1079 return this;
1080 }
1081
1082
1083
1084
1085
1086
1087 public List<RevCommit> parents() {
1088 return Collections.unmodifiableList(parents);
1089 }
1090
1091
1092
1093
1094
1095
1096 public CommitBuilder noParents() {
1097 parents.clear();
1098 return this;
1099 }
1100
1101
1102
1103
1104
1105
1106 public CommitBuilder noFiles() {
1107 tree.clear();
1108 return this;
1109 }
1110
1111
1112
1113
1114
1115
1116
1117
1118 public CommitBuilder setTopLevelTree(ObjectId treeId) {
1119 topLevelTree = treeId;
1120 return this;
1121 }
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 public CommitBuilder add(String path, String content) throws Exception {
1134 return add(path, blob(content));
1135 }
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147 public CommitBuilder add(String path, RevBlob id)
1148 throws Exception {
1149 return edit(new PathEdit(path) {
1150 @Override
1151 public void apply(DirCacheEntry ent) {
1152 ent.setFileMode(FileMode.REGULAR_FILE);
1153 ent.setObjectId(id);
1154 }
1155 });
1156 }
1157
1158
1159
1160
1161
1162
1163
1164
1165 public CommitBuilder edit(PathEdit edit) {
1166 DirCacheEditor e = tree.editor();
1167 e.add(edit);
1168 e.finish();
1169 return this;
1170 }
1171
1172
1173
1174
1175
1176
1177
1178
1179 public CommitBuilder rm(String path) {
1180 DirCacheEditor e = tree.editor();
1181 e.add(new DeletePath(path));
1182 e.add(new DeleteTree(path));
1183 e.finish();
1184 return this;
1185 }
1186
1187
1188
1189
1190
1191
1192
1193
1194 public CommitBuilder message(String m) {
1195 message = m;
1196 return this;
1197 }
1198
1199
1200
1201
1202
1203
1204 public String message() {
1205 return message;
1206 }
1207
1208
1209
1210
1211
1212
1213
1214
1215 public CommitBuilder tick(int secs) {
1216 tick = secs;
1217 return this;
1218 }
1219
1220
1221
1222
1223
1224
1225
1226
1227 public CommitBuilder ident(PersonIdent ident) {
1228 author = ident;
1229 committer = ident;
1230 return this;
1231 }
1232
1233
1234
1235
1236
1237
1238
1239
1240 public CommitBuilder author(PersonIdent a) {
1241 author = a;
1242 return this;
1243 }
1244
1245
1246
1247
1248
1249
1250 public PersonIdent author() {
1251 return author;
1252 }
1253
1254
1255
1256
1257
1258
1259
1260
1261 public CommitBuilder committer(PersonIdent c) {
1262 committer = c;
1263 return this;
1264 }
1265
1266
1267
1268
1269
1270
1271 public PersonIdent committer() {
1272 return committer;
1273 }
1274
1275
1276
1277
1278
1279
1280 public CommitBuilder insertChangeId() {
1281 changeId = "";
1282 return this;
1283 }
1284
1285
1286
1287
1288
1289
1290
1291
1292 public CommitBuilder insertChangeId(String c) {
1293
1294 ObjectId.fromString(c);
1295 changeId = c;
1296 return this;
1297 }
1298
1299
1300
1301
1302
1303
1304
1305
1306 public RevCommit create() throws Exception {
1307 if (self == null) {
1308 TestRepository.this.tick(tick);
1309
1310 final org.eclipse.jgit.lib.CommitBuilder c;
1311
1312 c = new org.eclipse.jgit.lib.CommitBuilder();
1313 c.setParentIds(parents);
1314 setAuthorAndCommitter(c);
1315 if (author != null)
1316 c.setAuthor(author);
1317 if (committer != null) {
1318 if (updateCommitterTime)
1319 committer = new PersonIdent(committer, getDate());
1320 c.setCommitter(committer);
1321 }
1322
1323 ObjectId commitId;
1324 try (ObjectInserter ins = inserter) {
1325 if (topLevelTree != null)
1326 c.setTreeId(topLevelTree);
1327 else
1328 c.setTreeId(tree.writeTree(ins));
1329 insertChangeId(c);
1330 c.setMessage(message);
1331 commitId = ins.insert(c);
1332 ins.flush();
1333 }
1334 self = pool.parseCommit(commitId);
1335
1336 if (branch != null)
1337 branch.update(self);
1338 }
1339 return self;
1340 }
1341
1342 private void insertChangeId(org.eclipse.jgit.lib.CommitBuilder c) {
1343 if (changeId == null)
1344 return;
1345 int idx = ChangeIdUtil.indexOfChangeId(message, "\n");
1346 if (idx >= 0)
1347 return;
1348
1349 ObjectId firstParentId = null;
1350 if (!parents.isEmpty())
1351 firstParentId = parents.get(0);
1352
1353 ObjectId cid;
1354 if (changeId.equals(""))
1355 cid = ChangeIdUtil.computeChangeId(c.getTreeId(), firstParentId,
1356 c.getAuthor(), c.getCommitter(), message);
1357 else
1358 cid = ObjectId.fromString(changeId);
1359 message = ChangeIdUtil.insertId(message, cid);
1360 if (cid != null)
1361 message = message.replaceAll("\nChange-Id: I"
1362 + ObjectId.zeroId().getName() + "\n", "\nChange-Id: I"
1363 + cid.getName() + "\n");
1364 }
1365
1366
1367
1368
1369
1370
1371
1372 public CommitBuilder child() throws Exception {
1373 return new CommitBuilder(this);
1374 }
1375 }
1376 }