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.Nullable;
56 import org.eclipse.jgit.internal.JGitText;
57 import org.eclipse.jgit.lib.AnyObjectId;
58 import org.eclipse.jgit.lib.ObjectId;
59 import org.eclipse.jgit.lib.Ref;
60 import org.eclipse.jgit.lib.RefUpdate;
61 import org.eclipse.jgit.revwalk.RevCommit;
62 import org.eclipse.jgit.revwalk.RevObject;
63 import org.eclipse.jgit.revwalk.RevWalk;
64
65
66
67
68
69
70
71 public class ReceiveCommand {
72
73 public static enum Type {
74
75 CREATE,
76
77
78
79
80
81
82
83 UPDATE,
84
85
86
87
88
89
90
91
92 UPDATE_NONFASTFORWARD,
93
94
95 DELETE;
96 }
97
98
99 public static enum Result {
100
101 NOT_ATTEMPTED,
102
103
104 REJECTED_NOCREATE,
105
106
107 REJECTED_NODELETE,
108
109
110 REJECTED_NONFASTFORWARD,
111
112
113 REJECTED_CURRENT_BRANCH,
114
115
116
117
118
119
120
121
122 REJECTED_MISSING_OBJECT,
123
124
125 REJECTED_OTHER_REASON,
126
127
128 LOCK_FAILURE,
129
130
131 OK;
132 }
133
134
135
136
137
138
139
140
141
142
143
144
145 public static List<ReceiveCommand> filter(Iterable<ReceiveCommand> in,
146 Result want) {
147 List<ReceiveCommand> r;
148 if (in instanceof Collection)
149 r = new ArrayList<>(((Collection<?>) in).size());
150 else
151 r = new ArrayList<>();
152 for (ReceiveCommand cmd : in) {
153 if (cmd.getResult() == want)
154 r.add(cmd);
155 }
156 return r;
157 }
158
159
160
161
162
163
164
165
166
167
168
169
170 public static List<ReceiveCommand> filter(List<ReceiveCommand> commands,
171 Result want) {
172 return filter((Iterable<ReceiveCommand>) commands, want);
173 }
174
175
176
177
178
179
180
181
182
183
184
185 public static void abort(Iterable<ReceiveCommand> commands) {
186 for (ReceiveCommand c : commands) {
187 if (c.getResult() == NOT_ATTEMPTED) {
188 c.setResult(REJECTED_OTHER_REASON,
189 JGitText.get().transactionAborted);
190 }
191 }
192 }
193
194
195
196
197
198
199
200
201
202
203 public static boolean isTransactionAborted(ReceiveCommand cmd) {
204 return cmd.getResult() == REJECTED_OTHER_REASON
205 && cmd.getMessage().equals(JGitText.get().transactionAborted);
206 }
207
208 private final ObjectId oldId;
209
210 private final ObjectId newId;
211
212 private final String name;
213
214 private Type type;
215
216 private Ref ref;
217
218 private Result status = Result.NOT_ATTEMPTED;
219
220 private String message;
221
222 private boolean customRefLog;
223
224 private String refLogMessage;
225
226 private boolean refLogIncludeResult;
227
228 private Boolean forceRefLog;
229
230 private boolean typeIsCorrect;
231
232
233
234
235
236
237
238
239
240
241
242
243
244 public ReceiveCommand(final ObjectId oldId, final ObjectId newId,
245 final String name) {
246 if (oldId == null) {
247 throw new IllegalArgumentException(JGitText.get().oldIdMustNotBeNull);
248 }
249 if (newId == null) {
250 throw new IllegalArgumentException(JGitText.get().newIdMustNotBeNull);
251 }
252 this.oldId = oldId;
253 this.newId = newId;
254 this.name = name;
255
256 type = Type.UPDATE;
257 if (ObjectId.zeroId().equals(oldId)) {
258 type = Type.CREATE;
259 }
260 if (ObjectId.zeroId().equals(newId)) {
261 type = Type.DELETE;
262 }
263 }
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281 public ReceiveCommand(final ObjectId oldId, final ObjectId newId,
282 final String name, final Type type) {
283 if (oldId == null) {
284 throw new IllegalArgumentException(JGitText.get().oldIdMustNotBeNull);
285 }
286 if (newId == null) {
287 throw new IllegalArgumentException(JGitText.get().newIdMustNotBeNull);
288 }
289 this.oldId = oldId;
290 this.newId = newId;
291 this.name = name;
292 switch (type) {
293 case CREATE:
294 if (!ObjectId.zeroId().equals(oldId)) {
295 throw new IllegalArgumentException(
296 JGitText.get().createRequiresZeroOldId);
297 }
298 break;
299 case DELETE:
300 if (!ObjectId.zeroId().equals(newId)) {
301 throw new IllegalArgumentException(
302 JGitText.get().deleteRequiresZeroNewId);
303 }
304 break;
305 case UPDATE:
306 case UPDATE_NONFASTFORWARD:
307 if (ObjectId.zeroId().equals(newId)
308 || ObjectId.zeroId().equals(oldId)) {
309 throw new IllegalArgumentException(
310 JGitText.get().updateRequiresOldIdAndNewId);
311 }
312 break;
313 default:
314 throw new IllegalStateException(JGitText.get().enumValueNotSupported0);
315 }
316 this.type = type;
317 }
318
319
320 public ObjectId getOldId() {
321 return oldId;
322 }
323
324
325 public ObjectId getNewId() {
326 return newId;
327 }
328
329
330 public String getRefName() {
331 return name;
332 }
333
334
335 public Type getType() {
336 return type;
337 }
338
339
340 public Ref getRef() {
341 return ref;
342 }
343
344
345 public Result getResult() {
346 return status;
347 }
348
349
350 public String getMessage() {
351 return message;
352 }
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368 public void setRefLogMessage(String msg, boolean appendStatus) {
369 customRefLog = true;
370 if (msg == null && !appendStatus) {
371 disableRefLog();
372 } else if (msg == null && appendStatus) {
373 refLogMessage = "";
374 refLogIncludeResult = true;
375 } else {
376 refLogMessage = msg;
377 refLogIncludeResult = appendStatus;
378 }
379 }
380
381
382
383
384
385
386
387
388 public void disableRefLog() {
389 customRefLog = true;
390 refLogMessage = null;
391 refLogIncludeResult = false;
392 }
393
394
395
396
397
398
399
400 public void setForceRefLog(boolean force) {
401 forceRefLog = Boolean.valueOf(force);
402 }
403
404
405
406
407
408
409
410
411
412
413
414
415 public boolean hasCustomRefLog() {
416 return customRefLog;
417 }
418
419
420
421
422
423
424
425 public boolean isRefLogDisabled() {
426 return refLogMessage == null;
427 }
428
429
430
431
432
433
434
435
436 @Nullable
437 public String getRefLogMessage() {
438 return refLogMessage;
439 }
440
441
442
443
444
445
446
447
448 public boolean isRefLogIncludingResult() {
449 return refLogIncludeResult;
450 }
451
452
453
454
455
456
457
458
459 @Nullable
460 public Boolean isForceRefLog() {
461 return forceRefLog;
462 }
463
464
465
466
467
468
469
470 public void setResult(final Result s) {
471 setResult(s, null);
472 }
473
474
475
476
477
478
479
480
481
482 public void setResult(final Result s, final String m) {
483 status = s;
484 message = m;
485 }
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503 public void updateType(RevWalk walk) throws IOException {
504 if (typeIsCorrect)
505 return;
506 if (type == Type.UPDATE && !AnyObjectId.equals(oldId, newId)) {
507 RevObject o = walk.parseAny(oldId);
508 RevObject n = walk.parseAny(newId);
509 if (!(o instanceof RevCommit)
510 || !(n instanceof RevCommit)
511 || !walk.isMergedInto((RevCommit) o, (RevCommit) n))
512 setType(Type.UPDATE_NONFASTFORWARD);
513 }
514 typeIsCorrect = true;
515 }
516
517
518
519
520
521
522
523
524
525
526 public void execute(final BaseReceivePack rp) {
527 try {
528 final RefUpdate ru = rp.getRepository().updateRef(getRefName());
529 ru.setRefLogIdent(rp.getRefLogIdent());
530 ru.setRefLogMessage(refLogMessage, refLogIncludeResult);
531 switch (getType()) {
532 case DELETE:
533 if (!ObjectId.zeroId().equals(getOldId())) {
534
535
536
537
538 ru.setExpectedOldObjectId(getOldId());
539 }
540 ru.setForceUpdate(true);
541 setResult(ru.delete(rp.getRevWalk()));
542 break;
543
544 case CREATE:
545 case UPDATE:
546 case UPDATE_NONFASTFORWARD:
547 ru.setForceUpdate(rp.isAllowNonFastForwards());
548 ru.setExpectedOldObjectId(getOldId());
549 ru.setNewObjectId(getNewId());
550 ru.setRefLogMessage("push", true);
551 setResult(ru.update(rp.getRevWalk()));
552 break;
553 }
554 } catch (IOException err) {
555 reject(err);
556 }
557 }
558
559 void setRef(final Ref r) {
560 ref = r;
561 }
562
563 void setType(final Type t) {
564 type = t;
565 }
566
567 void setTypeFastForwardUpdate() {
568 type = Type.UPDATE;
569 typeIsCorrect = true;
570 }
571
572
573
574
575
576
577
578 public void setResult(RefUpdate.Result r) {
579 switch (r) {
580 case NOT_ATTEMPTED:
581 setResult(Result.NOT_ATTEMPTED);
582 break;
583
584 case LOCK_FAILURE:
585 case IO_FAILURE:
586 setResult(Result.LOCK_FAILURE);
587 break;
588
589 case NO_CHANGE:
590 case NEW:
591 case FORCED:
592 case FAST_FORWARD:
593 setResult(Result.OK);
594 break;
595
596 case REJECTED:
597 setResult(Result.REJECTED_NONFASTFORWARD);
598 break;
599
600 case REJECTED_CURRENT_BRANCH:
601 setResult(Result.REJECTED_CURRENT_BRANCH);
602 break;
603
604 case REJECTED_MISSING_OBJECT:
605 setResult(Result.REJECTED_MISSING_OBJECT);
606 break;
607
608 case REJECTED_OTHER_REASON:
609 setResult(Result.REJECTED_OTHER_REASON);
610 break;
611
612 default:
613 setResult(Result.REJECTED_OTHER_REASON, r.name());
614 break;
615 }
616 }
617
618 void reject(IOException err) {
619 setResult(Result.REJECTED_OTHER_REASON, MessageFormat.format(
620 JGitText.get().lockError, err.getMessage()));
621 }
622
623 @SuppressWarnings("nls")
624 @Override
625 public String toString() {
626 return getType().name() + ": " + getOldId().name() + " "
627 + getNewId().name() + " " + getRefName();
628 }
629 }