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.transport;
45
46 import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
47 import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_OTHER_REASON;
48
49 import java.io.IOException;
50 import java.text.MessageFormat;
51 import java.util.ArrayList;
52 import java.util.Collection;
53 import java.util.List;
54
55 import org.eclipse.jgit.annotations.NonNull;
56 import org.eclipse.jgit.annotations.Nullable;
57 import org.eclipse.jgit.internal.JGitText;
58 import org.eclipse.jgit.lib.AnyObjectId;
59 import org.eclipse.jgit.lib.ObjectId;
60 import org.eclipse.jgit.lib.Ref;
61 import org.eclipse.jgit.lib.RefUpdate;
62 import org.eclipse.jgit.revwalk.RevCommit;
63 import org.eclipse.jgit.revwalk.RevObject;
64 import org.eclipse.jgit.revwalk.RevWalk;
65
66
67
68
69
70
71
72
73 public class ReceiveCommand {
74
75 public static enum Type {
76
77 CREATE,
78
79
80
81
82
83
84
85 UPDATE,
86
87
88
89
90
91
92
93
94 UPDATE_NONFASTFORWARD,
95
96
97 DELETE;
98 }
99
100
101 public static enum Result {
102
103 NOT_ATTEMPTED,
104
105
106 REJECTED_NOCREATE,
107
108
109 REJECTED_NODELETE,
110
111
112 REJECTED_NONFASTFORWARD,
113
114
115 REJECTED_CURRENT_BRANCH,
116
117
118
119
120
121
122
123
124 REJECTED_MISSING_OBJECT,
125
126
127 REJECTED_OTHER_REASON,
128
129
130 LOCK_FAILURE,
131
132
133 OK;
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147 public static List<ReceiveCommand> filter(Iterable<ReceiveCommand> in,
148 Result want) {
149 List<ReceiveCommand> r;
150 if (in instanceof Collection)
151 r = new ArrayList<>(((Collection<?>) in).size());
152 else
153 r = new ArrayList<>();
154 for (ReceiveCommand cmd : in) {
155 if (cmd.getResult() == want)
156 r.add(cmd);
157 }
158 return r;
159 }
160
161
162
163
164
165
166
167
168
169
170
171
172 public static List<ReceiveCommand> filter(List<ReceiveCommand> commands,
173 Result want) {
174 return filter((Iterable<ReceiveCommand>) commands, want);
175 }
176
177
178
179
180
181
182
183
184
185
186
187
188
189 public static void abort(Iterable<ReceiveCommand> commands) {
190 for (ReceiveCommand c : commands) {
191 if (c.getResult() == NOT_ATTEMPTED) {
192 c.setResult(REJECTED_OTHER_REASON,
193 JGitText.get().transactionAborted);
194 }
195 }
196 }
197
198
199
200
201
202
203
204
205
206
207 public static boolean isTransactionAborted(ReceiveCommand cmd) {
208 return cmd.getResult() == REJECTED_OTHER_REASON
209 && cmd.getMessage().equals(JGitText.get().transactionAborted);
210 }
211
212
213
214
215
216
217
218
219
220
221
222
223
224 public static ReceiveCommand link(@NonNull ObjectId oldId,
225 @NonNull String newTarget, @NonNull String name) {
226 return new ReceiveCommand(oldId, newTarget, name);
227 }
228
229
230
231
232
233
234
235
236
237
238
239
240
241 public static ReceiveCommand link(@Nullable String oldTarget,
242 @NonNull String newTarget, @NonNull String name) {
243 return new ReceiveCommand(oldTarget, newTarget, name);
244 }
245
246
247
248
249
250
251
252
253
254
255
256
257
258 public static ReceiveCommand unlink(@NonNull String oldTarget,
259 @NonNull ObjectId newId, @NonNull String name) {
260 return new ReceiveCommand(oldTarget, newId, name);
261 }
262
263 private final ObjectId oldId;
264
265 private final String oldSymref;
266
267 private final ObjectId newId;
268
269 private final String newSymref;
270
271 private final String name;
272
273 private Type type;
274
275 private boolean typeIsCorrect;
276
277 private Ref ref;
278
279 private Result status = Result.NOT_ATTEMPTED;
280
281 private String message;
282
283 private boolean customRefLog;
284
285 private String refLogMessage;
286
287 private boolean refLogIncludeResult;
288
289 private Boolean forceRefLog;
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306 public ReceiveCommand(final ObjectIdhtml#ObjectId">ObjectId oldId, final ObjectId newId,
307 final String name) {
308 if (oldId == null) {
309 throw new IllegalArgumentException(
310 JGitText.get().oldIdMustNotBeNull);
311 }
312 if (newId == null) {
313 throw new IllegalArgumentException(
314 JGitText.get().newIdMustNotBeNull);
315 }
316 if (name == null || name.isEmpty()) {
317 throw new IllegalArgumentException(
318 JGitText.get().nameMustNotBeNullOrEmpty);
319 }
320 this.oldId = oldId;
321 this.oldSymref = null;
322 this.newId = newId;
323 this.newSymref = null;
324 this.name = name;
325
326 type = Type.UPDATE;
327 if (ObjectId.zeroId().equals(oldId)) {
328 type = Type.CREATE;
329 }
330 if (ObjectId.zeroId().equals(newId)) {
331 type = Type.DELETE;
332 }
333 }
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358 public ReceiveCommand(final ObjectIdhtml#ObjectId">ObjectId oldId, final ObjectId newId,
359 final String name, final Type type) {
360 if (oldId == null) {
361 throw new IllegalArgumentException(
362 JGitText.get().oldIdMustNotBeNull);
363 }
364 if (newId == null) {
365 throw new IllegalArgumentException(
366 JGitText.get().newIdMustNotBeNull);
367 }
368 if (name == null || name.isEmpty()) {
369 throw new IllegalArgumentException(
370 JGitText.get().nameMustNotBeNullOrEmpty);
371 }
372 this.oldId = oldId;
373 this.oldSymref = null;
374 this.newId = newId;
375 this.newSymref = null;
376 this.name = name;
377 switch (type) {
378 case CREATE:
379 if (!ObjectId.zeroId().equals(oldId)) {
380 throw new IllegalArgumentException(
381 JGitText.get().createRequiresZeroOldId);
382 }
383 break;
384 case DELETE:
385 if (!ObjectId.zeroId().equals(newId)) {
386 throw new IllegalArgumentException(
387 JGitText.get().deleteRequiresZeroNewId);
388 }
389 break;
390 case UPDATE:
391 case UPDATE_NONFASTFORWARD:
392 if (ObjectId.zeroId().equals(newId)
393 || ObjectId.zeroId().equals(oldId)) {
394 throw new IllegalArgumentException(
395 JGitText.get().updateRequiresOldIdAndNewId);
396 }
397 break;
398 default:
399 throw new IllegalStateException(
400 JGitText.get().enumValueNotSupported0);
401 }
402 this.type = type;
403 }
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418 private ReceiveCommand(ObjectId oldId, String newSymref, String name) {
419 if (oldId == null) {
420 throw new IllegalArgumentException(
421 JGitText.get().oldIdMustNotBeNull);
422 }
423 if (name == null || name.isEmpty()) {
424 throw new IllegalArgumentException(
425 JGitText.get().nameMustNotBeNullOrEmpty);
426 }
427 this.oldId = oldId;
428 this.oldSymref = null;
429 this.newId = ObjectId.zeroId();
430 this.newSymref = newSymref;
431 this.name = name;
432 if (AnyObjectId.isEqual(ObjectId.zeroId(), oldId)) {
433 type = Type.CREATE;
434 } else if (newSymref != null) {
435 type = Type.UPDATE;
436 } else {
437 type = Type.DELETE;
438 }
439 typeIsCorrect = true;
440 }
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455 private ReceiveCommand(String oldSymref, ObjectId newId, String name) {
456 if (newId == null) {
457 throw new IllegalArgumentException(
458 JGitText.get().newIdMustNotBeNull);
459 }
460 if (name == null || name.isEmpty()) {
461 throw new IllegalArgumentException(
462 JGitText.get().nameMustNotBeNullOrEmpty);
463 }
464 this.oldId = ObjectId.zeroId();
465 this.oldSymref = oldSymref;
466 this.newId = newId;
467 this.newSymref = null;
468 this.name = name;
469 if (oldSymref == null) {
470 type = Type.CREATE;
471 } else if (!AnyObjectId.isEqual(ObjectId.zeroId(), newId)) {
472 type = Type.UPDATE;
473 } else {
474 type = Type.DELETE;
475 }
476 typeIsCorrect = true;
477 }
478
479
480
481
482
483
484
485
486
487
488
489
490
491 private ReceiveCommand(@Nullable String oldTarget, String newTarget, String name) {
492 if (name == null || name.isEmpty()) {
493 throw new IllegalArgumentException(
494 JGitText.get().nameMustNotBeNullOrEmpty);
495 }
496 this.oldId = ObjectId.zeroId();
497 this.oldSymref = oldTarget;
498 this.newId = ObjectId.zeroId();
499 this.newSymref = newTarget;
500 this.name = name;
501 if (oldTarget == null) {
502 if (newTarget == null) {
503 throw new IllegalArgumentException(
504 JGitText.get().bothRefTargetsMustNotBeNull);
505 }
506 type = Type.CREATE;
507 } else if (newTarget != null) {
508 type = Type.UPDATE;
509 } else {
510 type = Type.DELETE;
511 }
512 typeIsCorrect = true;
513 }
514
515
516
517
518
519
520 public ObjectId getOldId() {
521 return oldId;
522 }
523
524
525
526
527
528
529
530 @Nullable
531 public String getOldSymref() {
532 return oldSymref;
533 }
534
535
536
537
538
539
540 public ObjectId getNewId() {
541 return newId;
542 }
543
544
545
546
547
548
549
550 @Nullable
551 public String getNewSymref() {
552 return newSymref;
553 }
554
555
556
557
558
559
560 public String getRefName() {
561 return name;
562 }
563
564
565
566
567
568
569 public Type getType() {
570 return type;
571 }
572
573
574
575
576
577
578 public Ref getRef() {
579 return ref;
580 }
581
582
583
584
585
586
587 public Result getResult() {
588 return status;
589 }
590
591
592
593
594
595
596 public String getMessage() {
597 return message;
598 }
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614 public void setRefLogMessage(String msg, boolean appendStatus) {
615 customRefLog = true;
616 if (msg == null && !appendStatus) {
617 disableRefLog();
618 } else if (msg == null && appendStatus) {
619 refLogMessage = "";
620 refLogIncludeResult = true;
621 } else {
622 refLogMessage = msg;
623 refLogIncludeResult = appendStatus;
624 }
625 }
626
627
628
629
630
631
632
633
634 public void disableRefLog() {
635 customRefLog = true;
636 refLogMessage = null;
637 refLogIncludeResult = false;
638 }
639
640
641
642
643
644
645
646 public void setForceRefLog(boolean force) {
647 forceRefLog = Boolean.valueOf(force);
648 }
649
650
651
652
653
654
655
656
657
658
659
660
661 public boolean hasCustomRefLog() {
662 return customRefLog;
663 }
664
665
666
667
668
669
670
671 public boolean isRefLogDisabled() {
672 return refLogMessage == null;
673 }
674
675
676
677
678
679
680
681
682 @Nullable
683 public String getRefLogMessage() {
684 return refLogMessage;
685 }
686
687
688
689
690
691
692
693
694 public boolean isRefLogIncludingResult() {
695 return refLogIncludeResult;
696 }
697
698
699
700
701
702
703
704
705 @Nullable
706 public Boolean isForceRefLog() {
707 return forceRefLog;
708 }
709
710
711
712
713
714
715
716 public void setResult(Result s) {
717 setResult(s, null);
718 }
719
720
721
722
723
724
725
726
727
728 public void setResult(Result s, String m) {
729 status = s;
730 message = m;
731 }
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750 public void updateType(RevWalk walk) throws IOException {
751 if (typeIsCorrect)
752 return;
753 if (type == Type.UPDATE && !AnyObjectId.isEqual(oldId, newId)) {
754 RevObject o = walk.parseAny(oldId);
755 RevObject n = walk.parseAny(newId);
756 if (!(o instanceof RevCommit)
757 || !(n instanceof RevCommit)
758 || !walk.isMergedInto((RevCommit="../../../../org/eclipse/jgit/revwalk/RevCommit.html#RevCommit">RevCommit) o, (RevCommit) n))
759 setType(Type.UPDATE_NONFASTFORWARD);
760 }
761 typeIsCorrect = true;
762 }
763
764
765
766
767
768
769
770
771
772
773 public void execute(BaseReceivePack rp) {
774 try {
775 String expTarget = getOldSymref();
776 boolean detach = getNewSymref() != null
777 || (type == Type.DELETE && expTarget != null);
778 RefUpdate ru = rp.getRepository().updateRef(getRefName(), detach);
779 if (expTarget != null) {
780 if (!ru.getRef().isSymbolic() || !ru.getRef().getTarget()
781 .getName().equals(expTarget)) {
782 setResult(Result.LOCK_FAILURE);
783 return;
784 }
785 }
786
787 ru.setRefLogIdent(rp.getRefLogIdent());
788 ru.setRefLogMessage(refLogMessage, refLogIncludeResult);
789 switch (getType()) {
790 case DELETE:
791 if (!ObjectId.zeroId().equals(getOldId())) {
792
793
794
795
796 ru.setExpectedOldObjectId(getOldId());
797 }
798 ru.setForceUpdate(true);
799 setResult(ru.delete(rp.getRevWalk()));
800 break;
801
802 case CREATE:
803 case UPDATE:
804 case UPDATE_NONFASTFORWARD:
805 ru.setForceUpdate(rp.isAllowNonFastForwards());
806 ru.setExpectedOldObjectId(getOldId());
807 ru.setRefLogMessage("push", true);
808 if (getNewSymref() != null) {
809 setResult(ru.link(getNewSymref()));
810 } else {
811 ru.setNewObjectId(getNewId());
812 setResult(ru.update(rp.getRevWalk()));
813 }
814 break;
815 }
816 } catch (IOException err) {
817 reject(err);
818 }
819 }
820
821 void setRef(Ref r) {
822 ref = r;
823 }
824
825 void setType(Type t) {
826 type = t;
827 }
828
829 void setTypeFastForwardUpdate() {
830 type = Type.UPDATE;
831 typeIsCorrect = true;
832 }
833
834
835
836
837
838
839
840 public void setResult(RefUpdate.Result r) {
841 switch (r) {
842 case NOT_ATTEMPTED:
843 setResult(Result.NOT_ATTEMPTED);
844 break;
845
846 case LOCK_FAILURE:
847 case IO_FAILURE:
848 setResult(Result.LOCK_FAILURE);
849 break;
850
851 case NO_CHANGE:
852 case NEW:
853 case FORCED:
854 case FAST_FORWARD:
855 setResult(Result.OK);
856 break;
857
858 case REJECTED:
859 setResult(Result.REJECTED_NONFASTFORWARD);
860 break;
861
862 case REJECTED_CURRENT_BRANCH:
863 setResult(Result.REJECTED_CURRENT_BRANCH);
864 break;
865
866 case REJECTED_MISSING_OBJECT:
867 setResult(Result.REJECTED_MISSING_OBJECT);
868 break;
869
870 case REJECTED_OTHER_REASON:
871 setResult(Result.REJECTED_OTHER_REASON);
872 break;
873
874 default:
875 setResult(Result.REJECTED_OTHER_REASON, r.name());
876 break;
877 }
878 }
879
880 void reject(IOException err) {
881 setResult(Result.REJECTED_OTHER_REASON, MessageFormat.format(
882 JGitText.get().lockError, err.getMessage()));
883 }
884
885
886 @SuppressWarnings("nls")
887 @Override
888 public String toString() {
889 return getType().name() + ": " + getOldId().name() + " "
890 + getNewId().name() + " " + getRefName();
891 }
892 }