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