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 package org.eclipse.jgit.api;
44
45 import java.io.IOException;
46 import java.io.OutputStream;
47 import java.net.URISyntaxException;
48 import java.text.MessageFormat;
49 import java.util.ArrayList;
50 import java.util.Arrays;
51 import java.util.Collection;
52 import java.util.Collections;
53 import java.util.HashMap;
54 import java.util.List;
55 import java.util.Map;
56
57 import org.eclipse.jgit.api.errors.GitAPIException;
58 import org.eclipse.jgit.api.errors.InvalidRemoteException;
59 import org.eclipse.jgit.api.errors.JGitInternalException;
60 import org.eclipse.jgit.errors.NotSupportedException;
61 import org.eclipse.jgit.errors.TooLargeObjectInPackException;
62 import org.eclipse.jgit.errors.TooLargePackException;
63 import org.eclipse.jgit.errors.TransportException;
64 import org.eclipse.jgit.internal.JGitText;
65 import org.eclipse.jgit.lib.Constants;
66 import org.eclipse.jgit.lib.NullProgressMonitor;
67 import org.eclipse.jgit.lib.ProgressMonitor;
68 import org.eclipse.jgit.lib.Ref;
69 import org.eclipse.jgit.lib.Repository;
70 import org.eclipse.jgit.transport.PushResult;
71 import org.eclipse.jgit.transport.RefLeaseSpec;
72 import org.eclipse.jgit.transport.RefSpec;
73 import org.eclipse.jgit.transport.RemoteConfig;
74 import org.eclipse.jgit.transport.RemoteRefUpdate;
75 import org.eclipse.jgit.transport.Transport;
76
77
78
79
80
81
82
83
84
85 public class PushCommand extends
86 TransportCommand<PushCommand, Iterable<PushResult>> {
87
88 private String remote = Constants.DEFAULT_REMOTE_NAME;
89
90 private final List<RefSpec> refSpecs;
91
92 private final Map<String, RefLeaseSpec> refLeaseSpecs;
93
94 private ProgressMonitor monitor = NullProgressMonitor.INSTANCE;
95
96 private String receivePack = RemoteConfig.DEFAULT_RECEIVE_PACK;
97
98 private boolean dryRun;
99 private boolean atomic;
100 private boolean force;
101 private boolean thin = Transport.DEFAULT_PUSH_THIN;
102
103 private OutputStream out;
104
105 private List<String> pushOptions;
106
107
108
109
110
111
112
113
114
115 protected PushCommand(Repository repo) {
116 super(repo);
117 refSpecs = new ArrayList<>(3);
118 refLeaseSpecs = new HashMap<>();
119 }
120
121
122
123
124
125
126
127
128
129 @Override
130 public Iterable<PushResult> call() throws GitAPIException,
131 InvalidRemoteException,
132 org.eclipse.jgit.api.errors.TransportException {
133 checkCallable();
134
135 ArrayList<PushResult> pushResults = new ArrayList<>(3);
136
137 try {
138 if (refSpecs.isEmpty()) {
139 RemoteConfig config = new RemoteConfig(repo.getConfig(),
140 getRemote());
141 refSpecs.addAll(config.getPushRefSpecs());
142 }
143 if (refSpecs.isEmpty()) {
144 Ref head = repo.exactRef(Constants.HEAD);
145 if (head != null && head.isSymbolic())
146 refSpecs.add(new RefSpec(head.getLeaf().getName()));
147 }
148
149 if (force) {
150 for (int i = 0; i < refSpecs.size(); i++)
151 refSpecs.set(i, refSpecs.get(i).setForceUpdate(true));
152 }
153
154 final List<Transport> transports;
155 transports = Transport.openAll(repo, remote, Transport.Operation.PUSH);
156 for (@SuppressWarnings("resource")
157 final Transport transport : transports) {
158 transport.setPushThin(thin);
159 transport.setPushAtomic(atomic);
160 if (receivePack != null)
161 transport.setOptionReceivePack(receivePack);
162 transport.setDryRun(dryRun);
163 transport.setPushOptions(pushOptions);
164 configure(transport);
165
166 final Collection<RemoteRefUpdate> toPush = transport
167 .findRemoteRefUpdatesFor(refSpecs, refLeaseSpecs);
168
169 try {
170 PushResult result = transport.push(monitor, toPush, out);
171 pushResults.add(result);
172
173 } catch (TooLargePackException e) {
174 throw new org.eclipse.jgit.api.errors.TooLargePackException(
175 e.getMessage(), e);
176 } catch (TooLargeObjectInPackException e) {
177 throw new org.eclipse.jgit.api.errors.TooLargeObjectInPackException(
178 e.getMessage(), e);
179 } catch (TransportException e) {
180 throw new org.eclipse.jgit.api.errors.TransportException(
181 e.getMessage(), e);
182 } finally {
183 transport.close();
184 }
185 }
186
187 } catch (URISyntaxException e) {
188 throw new InvalidRemoteException(MessageFormat.format(
189 JGitText.get().invalidRemote, remote));
190 } catch (TransportException e) {
191 throw new org.eclipse.jgit.api.errors.TransportException(
192 e.getMessage(), e);
193 } catch (NotSupportedException e) {
194 throw new JGitInternalException(
195 JGitText.get().exceptionCaughtDuringExecutionOfPushCommand,
196 e);
197 } catch (IOException e) {
198 throw new JGitInternalException(
199 JGitText.get().exceptionCaughtDuringExecutionOfPushCommand,
200 e);
201 }
202
203 return pushResults;
204 }
205
206
207
208
209
210
211
212
213
214
215
216 public PushCommand setRemote(String remote) {
217 checkCallable();
218 this.remote = remote;
219 return this;
220 }
221
222
223
224
225
226
227 public String getRemote() {
228 return remote;
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242 public PushCommand setReceivePack(String receivePack) {
243 checkCallable();
244 this.receivePack = receivePack;
245 return this;
246 }
247
248
249
250
251
252
253 public String getReceivePack() {
254 return receivePack;
255 }
256
257
258
259
260
261
262 public int getTimeout() {
263 return timeout;
264 }
265
266
267
268
269
270
271 public ProgressMonitor getProgressMonitor() {
272 return monitor;
273 }
274
275
276
277
278
279
280
281
282
283
284 public PushCommand setProgressMonitor(ProgressMonitor monitor) {
285 checkCallable();
286 if (monitor == null) {
287 monitor = NullProgressMonitor.INSTANCE;
288 }
289 this.monitor = monitor;
290 return this;
291 }
292
293
294
295
296
297
298
299 public List<RefLeaseSpec> getRefLeaseSpecs() {
300 return new ArrayList<>(refLeaseSpecs.values());
301 }
302
303
304
305
306
307
308
309
310
311
312 public PushCommand setRefLeaseSpecs(RefLeaseSpec... specs) {
313 return setRefLeaseSpecs(Arrays.asList(specs));
314 }
315
316
317
318
319
320
321
322
323
324
325 public PushCommand setRefLeaseSpecs(List<RefLeaseSpec> specs) {
326 checkCallable();
327 this.refLeaseSpecs.clear();
328 for (RefLeaseSpec spec : specs) {
329 refLeaseSpecs.put(spec.getRef(), spec);
330 }
331 return this;
332 }
333
334
335
336
337
338
339 public List<RefSpec> getRefSpecs() {
340 return refSpecs;
341 }
342
343
344
345
346
347
348
349 public PushCommand setRefSpecs(RefSpec... specs) {
350 checkCallable();
351 this.refSpecs.clear();
352 Collections.addAll(refSpecs, specs);
353 return this;
354 }
355
356
357
358
359
360
361
362
363 public PushCommand setRefSpecs(List<RefSpec> specs) {
364 checkCallable();
365 this.refSpecs.clear();
366 this.refSpecs.addAll(specs);
367 return this;
368 }
369
370
371
372
373
374
375 public PushCommand setPushAll() {
376 refSpecs.add(Transport.REFSPEC_PUSH_ALL);
377 return this;
378 }
379
380
381
382
383
384
385 public PushCommand setPushTags() {
386 refSpecs.add(Transport.REFSPEC_TAGS);
387 return this;
388 }
389
390
391
392
393
394
395
396
397 public PushCommand add(Ref ref) {
398 refSpecs.add(new RefSpec(ref.getLeaf().getName()));
399 return this;
400 }
401
402
403
404
405
406
407
408
409
410
411 public PushCommand add(String nameOrSpec) {
412 if (0 <= nameOrSpec.indexOf(':')) {
413 refSpecs.add(new RefSpec(nameOrSpec));
414 } else {
415 Ref src;
416 try {
417 src = repo.findRef(nameOrSpec);
418 } catch (IOException e) {
419 throw new JGitInternalException(
420 JGitText.get().exceptionCaughtDuringExecutionOfPushCommand,
421 e);
422 }
423 if (src != null)
424 add(src);
425 }
426 return this;
427 }
428
429
430
431
432
433
434 public boolean isDryRun() {
435 return dryRun;
436 }
437
438
439
440
441
442
443
444 public PushCommand setDryRun(boolean dryRun) {
445 checkCallable();
446 this.dryRun = dryRun;
447 return this;
448 }
449
450
451
452
453
454
455 public boolean isThin() {
456 return thin;
457 }
458
459
460
461
462
463
464
465
466
467
468 public PushCommand setThin(boolean thin) {
469 checkCallable();
470 this.thin = thin;
471 return this;
472 }
473
474
475
476
477
478
479
480
481 public boolean isAtomic() {
482 return atomic;
483 }
484
485
486
487
488
489
490
491
492
493
494
495 public PushCommand setAtomic(boolean atomic) {
496 checkCallable();
497 this.atomic = atomic;
498 return this;
499 }
500
501
502
503
504
505
506 public boolean isForce() {
507 return force;
508 }
509
510
511
512
513
514
515
516
517 public PushCommand setForce(boolean force) {
518 checkCallable();
519 this.force = force;
520 return this;
521 }
522
523
524
525
526
527
528
529
530
531 public PushCommand setOutputStream(OutputStream out) {
532 this.out = out;
533 return this;
534 }
535
536
537
538
539
540
541
542 public List<String> getPushOptions() {
543 return pushOptions;
544 }
545
546
547
548
549
550
551
552
553
554 public PushCommand setPushOptions(List<String> pushOptions) {
555 this.pushOptions = pushOptions;
556 return this;
557 }
558 }