1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.api;
11
12 import java.io.IOException;
13 import java.io.InputStream;
14 import java.io.PrintStream;
15 import java.text.MessageFormat;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.LinkedList;
20 import java.util.List;
21
22 import org.eclipse.jgit.api.errors.AbortedByHookException;
23 import org.eclipse.jgit.api.errors.CanceledException;
24 import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
25 import org.eclipse.jgit.api.errors.EmptyCommitException;
26 import org.eclipse.jgit.api.errors.GitAPIException;
27 import org.eclipse.jgit.api.errors.JGitInternalException;
28 import org.eclipse.jgit.api.errors.NoFilepatternException;
29 import org.eclipse.jgit.api.errors.NoHeadException;
30 import org.eclipse.jgit.api.errors.NoMessageException;
31 import org.eclipse.jgit.api.errors.ServiceUnavailableException;
32 import org.eclipse.jgit.api.errors.UnmergedPathsException;
33 import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
34 import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
35 import org.eclipse.jgit.dircache.DirCache;
36 import org.eclipse.jgit.dircache.DirCacheBuildIterator;
37 import org.eclipse.jgit.dircache.DirCacheBuilder;
38 import org.eclipse.jgit.dircache.DirCacheEntry;
39 import org.eclipse.jgit.dircache.DirCacheIterator;
40 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
41 import org.eclipse.jgit.errors.MissingObjectException;
42 import org.eclipse.jgit.errors.UnmergedPathException;
43 import org.eclipse.jgit.hooks.CommitMsgHook;
44 import org.eclipse.jgit.hooks.Hooks;
45 import org.eclipse.jgit.hooks.PostCommitHook;
46 import org.eclipse.jgit.hooks.PreCommitHook;
47 import org.eclipse.jgit.internal.JGitText;
48 import org.eclipse.jgit.lib.CommitBuilder;
49 import org.eclipse.jgit.lib.Constants;
50 import org.eclipse.jgit.lib.FileMode;
51 import org.eclipse.jgit.lib.GpgConfig;
52 import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
53 import org.eclipse.jgit.lib.GpgObjectSigner;
54 import org.eclipse.jgit.lib.GpgSigner;
55 import org.eclipse.jgit.lib.ObjectId;
56 import org.eclipse.jgit.lib.ObjectInserter;
57 import org.eclipse.jgit.lib.PersonIdent;
58 import org.eclipse.jgit.lib.Ref;
59 import org.eclipse.jgit.lib.RefUpdate;
60 import org.eclipse.jgit.lib.RefUpdate.Result;
61 import org.eclipse.jgit.lib.Repository;
62 import org.eclipse.jgit.lib.RepositoryState;
63 import org.eclipse.jgit.revwalk.RevCommit;
64 import org.eclipse.jgit.revwalk.RevObject;
65 import org.eclipse.jgit.revwalk.RevTag;
66 import org.eclipse.jgit.revwalk.RevWalk;
67 import org.eclipse.jgit.transport.CredentialsProvider;
68 import org.eclipse.jgit.treewalk.CanonicalTreeParser;
69 import org.eclipse.jgit.treewalk.FileTreeIterator;
70 import org.eclipse.jgit.treewalk.TreeWalk;
71 import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
72 import org.eclipse.jgit.util.ChangeIdUtil;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75
76
77
78
79
80
81
82
83
84
85 public class CommitCommand extends GitCommand<RevCommit> {
86 private static final Logger log = LoggerFactory
87 .getLogger(CommitCommand.class);
88
89 private PersonIdent author;
90
91 private PersonIdent committer;
92
93 private String message;
94
95 private boolean all;
96
97 private List<String> only = new ArrayList<>();
98
99 private boolean[] onlyProcessed;
100
101 private boolean amend;
102
103 private boolean insertChangeId;
104
105
106
107
108
109 private List<ObjectId> parents = new LinkedList<>();
110
111 private String reflogComment;
112
113 private boolean useDefaultReflogMessage = true;
114
115
116
117
118 private boolean noVerify;
119
120 private HashMap<String, PrintStream> hookOutRedirect = new HashMap<>(3);
121
122 private HashMap<String, PrintStream> hookErrRedirect = new HashMap<>(3);
123
124 private Boolean allowEmpty;
125
126 private Boolean signCommit;
127
128 private String signingKey;
129
130 private GpgSigner gpgSigner;
131
132 private GpgConfig gpgConfig;
133
134 private CredentialsProvider credentialsProvider;
135
136
137
138
139
140
141
142 protected CommitCommand(Repository repo) {
143 super(repo);
144 this.credentialsProvider = CredentialsProvider.getDefault();
145 }
146
147
148
149
150
151
152
153
154
155
156
157
158
159 @Override
160 public RevCommit call() throws GitAPIException, AbortedByHookException,
161 ConcurrentRefUpdateException, NoHeadException, NoMessageException,
162 ServiceUnavailableException, UnmergedPathsException,
163 WrongRepositoryStateException {
164 checkCallable();
165 Collections.sort(only);
166
167 try (RevWalk rw = new RevWalk(repo)) {
168 RepositoryState state = repo.getRepositoryState();
169 if (!state.canCommit())
170 throw new WrongRepositoryStateException(MessageFormat.format(
171 JGitText.get().cannotCommitOnARepoWithState,
172 state.name()));
173
174 if (!noVerify) {
175 Hooks.preCommit(repo, hookOutRedirect.get(PreCommitHook.NAME),
176 hookErrRedirect.get(PreCommitHook.NAME))
177 .call();
178 }
179
180 processOptions(state, rw);
181
182 if (all && !repo.isBare()) {
183 try (Git git = new Git(repo)) {
184 git.add().addFilepattern(".")
185 .setUpdate(true).call();
186 } catch (NoFilepatternException e) {
187
188 throw new JGitInternalException(e.getMessage(), e);
189 }
190 }
191
192 Ref head = repo.exactRef(Constants.HEAD);
193 if (head == null)
194 throw new NoHeadException(
195 JGitText.get().commitOnRepoWithoutHEADCurrentlyNotSupported);
196
197
198 ObjectId headId = repo.resolve(Constants.HEAD + "^{commit}");
199 if (headId == null && amend)
200 throw new WrongRepositoryStateException(
201 JGitText.get().commitAmendOnInitialNotPossible);
202
203 if (headId != null)
204 if (amend) {
205 RevCommit previousCommit = rw.parseCommit(headId);
206 for (RevCommit p : previousCommit.getParents())
207 parents.add(p.getId());
208 if (author == null)
209 author = previousCommit.getAuthorIdent();
210 } else {
211 parents.add(0, headId);
212 }
213
214 if (!noVerify) {
215 message = Hooks
216 .commitMsg(repo,
217 hookOutRedirect.get(CommitMsgHook.NAME),
218 hookErrRedirect.get(CommitMsgHook.NAME))
219 .setCommitMessage(message).call();
220 }
221
222 RevCommit revCommit;
223 DirCache index = repo.lockDirCache();
224 try (ObjectInserter odi = repo.newObjectInserter()) {
225 if (!only.isEmpty())
226 index = createTemporaryIndex(headId, index, rw);
227
228
229
230
231 ObjectId indexTreeId = index.writeTree(odi);
232
233 if (insertChangeId)
234 insertChangeId(indexTreeId);
235
236 checkIfEmpty(rw, headId, indexTreeId);
237
238
239 CommitBuilder commit = new CommitBuilder();
240 commit.setCommitter(committer);
241 commit.setAuthor(author);
242 commit.setMessage(message);
243 commit.setParentIds(parents);
244 commit.setTreeId(indexTreeId);
245
246 if (signCommit.booleanValue()) {
247 sign(commit);
248 }
249
250 ObjectId commitId = odi.insert(commit);
251 odi.flush();
252 revCommit = rw.parseCommit(commitId);
253
254 updateRef(state, headId, revCommit, commitId);
255 } finally {
256 index.unlock();
257 }
258 try {
259 Hooks.postCommit(repo, hookOutRedirect.get(PostCommitHook.NAME),
260 hookErrRedirect.get(PostCommitHook.NAME)).call();
261 } catch (Exception e) {
262 log.error(MessageFormat.format(
263 JGitText.get().postCommitHookFailed, e.getMessage()),
264 e);
265 }
266 return revCommit;
267 } catch (UnmergedPathException e) {
268 throw new UnmergedPathsException(e);
269 } catch (IOException e) {
270 throw new JGitInternalException(
271 JGitText.get().exceptionCaughtDuringExecutionOfCommitCommand, e);
272 }
273 }
274
275 private void checkIfEmpty(RevWalk rw, ObjectId headId, ObjectId indexTreeId)
276 throws EmptyCommitException, MissingObjectException,
277 IncorrectObjectTypeException, IOException {
278 if (headId != null && !allowEmpty.booleanValue()) {
279 RevCommit headCommit = rw.parseCommit(headId);
280 headCommit.getTree();
281 if (indexTreeId.equals(headCommit.getTree())) {
282 throw new EmptyCommitException(JGitText.get().emptyCommit);
283 }
284 }
285 }
286
287 private void sign(CommitBuilder commit) throws ServiceUnavailableException,
288 CanceledException, UnsupportedSigningFormatException {
289 if (gpgSigner == null) {
290 throw new ServiceUnavailableException(
291 JGitText.get().signingServiceUnavailable);
292 }
293 if (gpgSigner instanceof GpgObjectSigner) {
294 ((GpgObjectSigner) gpgSigner).signObject(commit,
295 signingKey, committer, credentialsProvider,
296 gpgConfig);
297 } else {
298 if (gpgConfig.getKeyFormat() != GpgFormat.OPENPGP) {
299 throw new UnsupportedSigningFormatException(JGitText
300 .get().onlyOpenPgpSupportedForSigning);
301 }
302 gpgSigner.sign(commit, signingKey, committer,
303 credentialsProvider);
304 }
305 }
306
307 private void updateRef(RepositoryState state, ObjectId headId,
308 RevCommit revCommit, ObjectId commitId)
309 throws ConcurrentRefUpdateException, IOException {
310 RefUpdate ru = repo.updateRef(Constants.HEAD);
311 ru.setNewObjectId(commitId);
312 if (!useDefaultReflogMessage) {
313 ru.setRefLogMessage(reflogComment, false);
314 } else {
315 String prefix = amend ? "commit (amend): "
316 : parents.isEmpty() ? "commit (initial): "
317 : "commit: ";
318 ru.setRefLogMessage(prefix + revCommit.getShortMessage(),
319 false);
320 }
321 if (headId != null) {
322 ru.setExpectedOldObjectId(headId);
323 } else {
324 ru.setExpectedOldObjectId(ObjectId.zeroId());
325 }
326 Result rc = ru.forceUpdate();
327 switch (rc) {
328 case NEW:
329 case FORCED:
330 case FAST_FORWARD: {
331 setCallable(false);
332 if (state == RepositoryState.MERGING_RESOLVED
333 || isMergeDuringRebase(state)) {
334
335
336 repo.writeMergeCommitMsg(null);
337 repo.writeMergeHeads(null);
338 } else if (state == RepositoryState.CHERRY_PICKING_RESOLVED) {
339 repo.writeMergeCommitMsg(null);
340 repo.writeCherryPickHead(null);
341 } else if (state == RepositoryState.REVERTING_RESOLVED) {
342 repo.writeMergeCommitMsg(null);
343 repo.writeRevertHead(null);
344 }
345 break;
346 }
347 case REJECTED:
348 case LOCK_FAILURE:
349 throw new ConcurrentRefUpdateException(
350 JGitText.get().couldNotLockHEAD, ru.getRef(), rc);
351 default:
352 throw new JGitInternalException(MessageFormat.format(
353 JGitText.get().updatingRefFailed, Constants.HEAD,
354 commitId.toString(), rc));
355 }
356 }
357
358 private void insertChangeId(ObjectId treeId) {
359 ObjectId firstParentId = null;
360 if (!parents.isEmpty())
361 firstParentId = parents.get(0);
362 ObjectId changeId = ChangeIdUtil.computeChangeId(treeId, firstParentId,
363 author, committer, message);
364 message = ChangeIdUtil.insertId(message, changeId);
365 if (changeId != null)
366 message = message.replaceAll("\nChange-Id: I"
367 + ObjectId.zeroId().getName() + "\n", "\nChange-Id: I"
368 + changeId.getName() + "\n");
369 }
370
371 private DirCache createTemporaryIndex(ObjectId headId, DirCache index,
372 RevWalk rw)
373 throws IOException {
374 ObjectInserter inserter = null;
375
376
377 DirCacheBuilder existingBuilder = index.builder();
378
379
380
381 DirCache inCoreIndex = DirCache.newInCore();
382 DirCacheBuilder tempBuilder = inCoreIndex.builder();
383
384 onlyProcessed = new boolean[only.size()];
385 boolean emptyCommit = true;
386
387 try (TreeWalk treeWalk = new TreeWalk(repo)) {
388 treeWalk.setOperationType(OperationType.CHECKIN_OP);
389 int dcIdx = treeWalk
390 .addTree(new DirCacheBuildIterator(existingBuilder));
391 FileTreeIterator fti = new FileTreeIterator(repo);
392 fti.setDirCacheIterator(treeWalk, 0);
393 int fIdx = treeWalk.addTree(fti);
394 int hIdx = -1;
395 if (headId != null)
396 hIdx = treeWalk.addTree(rw.parseTree(headId));
397 treeWalk.setRecursive(true);
398
399 String lastAddedFile = null;
400 while (treeWalk.next()) {
401 String path = treeWalk.getPathString();
402
403 int pos = lookupOnly(path);
404
405 CanonicalTreeParser hTree = null;
406 if (hIdx != -1)
407 hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class);
408
409 DirCacheIterator dcTree = treeWalk.getTree(dcIdx,
410 DirCacheIterator.class);
411
412 if (pos >= 0) {
413
414
415 FileTreeIterator fTree = treeWalk.getTree(fIdx,
416 FileTreeIterator.class);
417
418
419 boolean tracked = dcTree != null || hTree != null;
420 if (!tracked)
421 continue;
422
423
424
425 if (path.equals(lastAddedFile))
426 continue;
427
428 lastAddedFile = path;
429
430 if (fTree != null) {
431
432
433 final DirCacheEntry dcEntry = new DirCacheEntry(path);
434 long entryLength = fTree.getEntryLength();
435 dcEntry.setLength(entryLength);
436 dcEntry.setLastModified(fTree.getEntryLastModifiedInstant());
437 dcEntry.setFileMode(fTree.getIndexFileMode(dcTree));
438
439 boolean objectExists = (dcTree != null
440 && fTree.idEqual(dcTree))
441 || (hTree != null && fTree.idEqual(hTree));
442 if (objectExists) {
443 dcEntry.setObjectId(fTree.getEntryObjectId());
444 } else {
445 if (FileMode.GITLINK.equals(dcEntry.getFileMode()))
446 dcEntry.setObjectId(fTree.getEntryObjectId());
447 else {
448
449 if (inserter == null)
450 inserter = repo.newObjectInserter();
451 long contentLength = fTree
452 .getEntryContentLength();
453 try (InputStream inputStream = fTree
454 .openEntryStream()) {
455 dcEntry.setObjectId(inserter.insert(
456 Constants.OBJ_BLOB, contentLength,
457 inputStream));
458 }
459 }
460 }
461
462
463 existingBuilder.add(dcEntry);
464
465 tempBuilder.add(dcEntry);
466
467 if (emptyCommit
468 && (hTree == null || !hTree.idEqual(fTree)
469 || hTree.getEntryRawMode() != fTree
470 .getEntryRawMode()))
471
472 emptyCommit = false;
473 } else {
474
475
476
477 if (emptyCommit && hTree != null)
478
479 emptyCommit = false;
480 }
481
482
483 onlyProcessed[pos] = true;
484 } else {
485
486 if (hTree != null) {
487
488
489 final DirCacheEntry dcEntry = new DirCacheEntry(path);
490 dcEntry.setObjectId(hTree.getEntryObjectId());
491 dcEntry.setFileMode(hTree.getEntryFileMode());
492
493
494 tempBuilder.add(dcEntry);
495 }
496
497
498 if (dcTree != null)
499 existingBuilder.add(dcTree.getDirCacheEntry());
500 }
501 }
502 }
503
504
505
506 for (int i = 0; i < onlyProcessed.length; i++)
507 if (!onlyProcessed[i])
508 throw new JGitInternalException(MessageFormat.format(
509 JGitText.get().entryNotFoundByPath, only.get(i)));
510
511
512 if (emptyCommit && !allowEmpty.booleanValue())
513
514
515 throw new JGitInternalException(JGitText.get().emptyCommit);
516
517
518 existingBuilder.commit();
519
520 tempBuilder.finish();
521 return inCoreIndex;
522 }
523
524
525
526
527
528
529
530
531
532
533
534
535
536 private int lookupOnly(String pathString) {
537 String p = pathString;
538 while (true) {
539 int position = Collections.binarySearch(only, p);
540 if (position >= 0)
541 return position;
542 int l = p.lastIndexOf('/');
543 if (l < 1)
544 break;
545 p = p.substring(0, l);
546 }
547 return -1;
548 }
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564 private void processOptions(RepositoryState state, RevWalk rw)
565 throws NoMessageException, UnsupportedSigningFormatException {
566 if (committer == null)
567 committer = new PersonIdent(repo);
568 if (author == null && !amend)
569 author = committer;
570 if (allowEmpty == null)
571
572
573
574
575 allowEmpty = (only.isEmpty()) ? Boolean.TRUE : Boolean.FALSE;
576
577
578 if (state == RepositoryState.MERGING_RESOLVED
579 || isMergeDuringRebase(state)) {
580 try {
581 parents = repo.readMergeHeads();
582 if (parents != null)
583 for (int i = 0; i < parents.size(); i++) {
584 RevObject ro = rw.parseAny(parents.get(i));
585 if (ro instanceof RevTag)
586 parents.set(i, rw.peel(ro));
587 }
588 } catch (IOException e) {
589 throw new JGitInternalException(MessageFormat.format(
590 JGitText.get().exceptionOccurredDuringReadingOfGIT_DIR,
591 Constants.MERGE_HEAD, e), e);
592 }
593 if (message == null) {
594 try {
595 message = repo.readMergeCommitMsg();
596 } catch (IOException e) {
597 throw new JGitInternalException(MessageFormat.format(
598 JGitText.get().exceptionOccurredDuringReadingOfGIT_DIR,
599 Constants.MERGE_MSG, e), e);
600 }
601 }
602 } else if (state == RepositoryState.SAFE && message == null) {
603 try {
604 message = repo.readSquashCommitMsg();
605 if (message != null)
606 repo.writeSquashCommitMsg(null );
607 } catch (IOException e) {
608 throw new JGitInternalException(MessageFormat.format(
609 JGitText.get().exceptionOccurredDuringReadingOfGIT_DIR,
610 Constants.MERGE_MSG, e), e);
611 }
612
613 }
614 if (message == null)
615
616
617 throw new NoMessageException(JGitText.get().commitMessageNotSpecified);
618
619 if (gpgConfig == null) {
620 gpgConfig = new GpgConfig(repo.getConfig());
621 }
622 if (signCommit == null) {
623 signCommit = gpgConfig.isSignCommits() ? Boolean.TRUE
624 : Boolean.FALSE;
625 }
626 if (signingKey == null) {
627 signingKey = gpgConfig.getSigningKey();
628 }
629 if (gpgSigner == null) {
630 gpgSigner = GpgSigner.getDefault();
631 }
632 }
633
634 private boolean isMergeDuringRebase(RepositoryState state) {
635 if (state != RepositoryState.REBASING_INTERACTIVE
636 && state != RepositoryState.REBASING_MERGE)
637 return false;
638 try {
639 return repo.readMergeHeads() != null;
640 } catch (IOException e) {
641 throw new JGitInternalException(MessageFormat.format(
642 JGitText.get().exceptionOccurredDuringReadingOfGIT_DIR,
643 Constants.MERGE_HEAD, e), e);
644 }
645 }
646
647
648
649
650
651
652
653
654 public CommitCommand setMessage(String message) {
655 checkCallable();
656 this.message = message;
657 return this;
658 }
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679 public CommitCommand setAllowEmpty(boolean allowEmpty) {
680 this.allowEmpty = Boolean.valueOf(allowEmpty);
681 return this;
682 }
683
684
685
686
687
688
689 public String getMessage() {
690 return message;
691 }
692
693
694
695
696
697
698
699
700
701
702
703 public CommitCommand setCommitter(PersonIdent committer) {
704 checkCallable();
705 this.committer = committer;
706 return this;
707 }
708
709
710
711
712
713
714
715
716
717
718
719
720 public CommitCommand setCommitter(String name, String email) {
721 checkCallable();
722 return setCommitter(new PersonIdent(name, email));
723 }
724
725
726
727
728
729
730
731
732
733 public PersonIdent getCommitter() {
734 return committer;
735 }
736
737
738
739
740
741
742
743
744
745
746
747 public CommitCommand setAuthor(PersonIdent author) {
748 checkCallable();
749 this.author = author;
750 return this;
751 }
752
753
754
755
756
757
758
759
760
761
762
763
764 public CommitCommand setAuthor(String name, String email) {
765 checkCallable();
766 return setAuthor(new PersonIdent(name, email));
767 }
768
769
770
771
772
773
774
775
776
777 public PersonIdent getAuthor() {
778 return author;
779 }
780
781
782
783
784
785
786
787
788
789
790
791
792
793 public CommitCommand setAll(boolean all) {
794 checkCallable();
795 if (all && !only.isEmpty())
796 throw new JGitInternalException(MessageFormat.format(
797 JGitText.get().illegalCombinationOfArguments, "--all",
798 "--only"));
799 this.all = all;
800 return this;
801 }
802
803
804
805
806
807
808
809
810
811
812 public CommitCommand setAmend(boolean amend) {
813 checkCallable();
814 this.amend = amend;
815 return this;
816 }
817
818
819
820
821
822
823
824
825
826
827
828
829 public CommitCommand setOnly(String only) {
830 checkCallable();
831 if (all)
832 throw new JGitInternalException(MessageFormat.format(
833 JGitText.get().illegalCombinationOfArguments, "--only",
834 "--all"));
835 String o = only.endsWith("/") ? only.substring(0, only.length() - 1)
836 : only;
837
838 if (!this.only.contains(o))
839 this.only.add(o);
840 return this;
841 }
842
843
844
845
846
847
848
849
850
851
852
853 public CommitCommand setInsertChangeId(boolean insertChangeId) {
854 checkCallable();
855 this.insertChangeId = insertChangeId;
856 return this;
857 }
858
859
860
861
862
863
864
865
866
867 public CommitCommand setReflogComment(String reflogComment) {
868 this.reflogComment = reflogComment;
869 useDefaultReflogMessage = false;
870 return this;
871 }
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887 public CommitCommand setNoVerify(boolean noVerify) {
888 this.noVerify = noVerify;
889 return this;
890 }
891
892
893
894
895
896
897
898
899
900
901
902 public CommitCommand setHookOutputStream(PrintStream hookStdOut) {
903 setHookOutputStream(PreCommitHook.NAME, hookStdOut);
904 setHookOutputStream(CommitMsgHook.NAME, hookStdOut);
905 setHookOutputStream(PostCommitHook.NAME, hookStdOut);
906 return this;
907 }
908
909
910
911
912
913
914
915
916
917
918
919 public CommitCommand setHookErrorStream(PrintStream hookStdErr) {
920 setHookErrorStream(PreCommitHook.NAME, hookStdErr);
921 setHookErrorStream(CommitMsgHook.NAME, hookStdErr);
922 setHookErrorStream(PostCommitHook.NAME, hookStdErr);
923 return this;
924 }
925
926
927
928
929
930
931
932
933
934
935
936
937
938 public CommitCommand setHookOutputStream(String hookName,
939 PrintStream hookStdOut) {
940 if (!(PreCommitHook.NAME.equals(hookName)
941 || CommitMsgHook.NAME.equals(hookName)
942 || PostCommitHook.NAME.equals(hookName))) {
943 throw new IllegalArgumentException(
944 MessageFormat.format(JGitText.get().illegalHookName,
945 hookName));
946 }
947 hookOutRedirect.put(hookName, hookStdOut);
948 return this;
949 }
950
951
952
953
954
955
956
957
958
959
960
961
962
963 public CommitCommand setHookErrorStream(String hookName,
964 PrintStream hookStdErr) {
965 if (!(PreCommitHook.NAME.equals(hookName)
966 || CommitMsgHook.NAME.equals(hookName)
967 || PostCommitHook.NAME.equals(hookName))) {
968 throw new IllegalArgumentException(MessageFormat
969 .format(JGitText.get().illegalHookName, hookName));
970 }
971 hookErrRedirect.put(hookName, hookStdErr);
972 return this;
973 }
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991 public CommitCommand setSigningKey(String signingKey) {
992 checkCallable();
993 this.signingKey = signingKey;
994 return this;
995 }
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007 public CommitCommand setSign(Boolean sign) {
1008 checkCallable();
1009 this.signCommit = sign;
1010 return this;
1011 }
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021 public CommitCommand setGpgSigner(GpgSigner signer) {
1022 checkCallable();
1023 this.gpgSigner = signer;
1024 return this;
1025 }
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037 public CommitCommand setGpgConfig(GpgConfig config) {
1038 checkCallable();
1039 this.gpgConfig = config;
1040 return this;
1041 }
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051 public void setCredentialsProvider(
1052 CredentialsProvider credentialsProvider) {
1053 this.credentialsProvider = credentialsProvider;
1054 }
1055 }