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 protected PushCommand(Repository repo) {
111 super(repo);
112 refSpecs = new ArrayList<>(3);
113 refLeaseSpecs = new HashMap<>();
114 }
115
116
117
118
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 (final Transport transport : transports) {
157 transport.setPushThin(thin);
158 transport.setPushAtomic(atomic);
159 if (receivePack != null)
160 transport.setOptionReceivePack(receivePack);
161 transport.setDryRun(dryRun);
162 transport.setPushOptions(pushOptions);
163 configure(transport);
164
165 final Collection<RemoteRefUpdate> toPush = transport
166 .findRemoteRefUpdatesFor(refSpecs, refLeaseSpecs);
167
168 try {
169 PushResult result = transport.push(monitor, toPush, out);
170 pushResults.add(result);
171
172 } catch (TooLargePackException e) {
173 throw new org.eclipse.jgit.api.errors.TooLargePackException(
174 e.getMessage(), e);
175 } catch (TooLargeObjectInPackException e) {
176 throw new org.eclipse.jgit.api.errors.TooLargeObjectInPackException(
177 e.getMessage(), e);
178 } catch (TransportException e) {
179 throw new org.eclipse.jgit.api.errors.TransportException(
180 e.getMessage(), e);
181 } finally {
182 transport.close();
183 }
184 }
185
186 } catch (URISyntaxException e) {
187 throw new InvalidRemoteException(MessageFormat.format(
188 JGitText.get().invalidRemote, remote));
189 } catch (TransportException e) {
190 throw new org.eclipse.jgit.api.errors.TransportException(
191 e.getMessage(), e);
192 } catch (NotSupportedException e) {
193 throw new JGitInternalException(
194 JGitText.get().exceptionCaughtDuringExecutionOfPushCommand,
195 e);
196 } catch (IOException e) {
197 throw new JGitInternalException(
198 JGitText.get().exceptionCaughtDuringExecutionOfPushCommand,
199 e);
200 }
201
202 return pushResults;
203 }
204
205
206
207
208
209
210
211
212
213
214 public PushCommand setRemote(String remote) {
215 checkCallable();
216 this.remote = remote;
217 return this;
218 }
219
220
221
222
223 public String getRemote() {
224 return remote;
225 }
226
227
228
229
230
231
232
233
234
235
236 public PushCommand setReceivePack(String receivePack) {
237 checkCallable();
238 this.receivePack = receivePack;
239 return this;
240 }
241
242
243
244
245 public String getReceivePack() {
246 return receivePack;
247 }
248
249
250
251
252 public int getTimeout() {
253 return timeout;
254 }
255
256
257
258
259 public ProgressMonitor getProgressMonitor() {
260 return monitor;
261 }
262
263
264
265
266
267
268
269
270
271
272 public PushCommand setProgressMonitor(ProgressMonitor monitor) {
273 checkCallable();
274 if (monitor == null) {
275 monitor = NullProgressMonitor.INSTANCE;
276 }
277 this.monitor = monitor;
278 return this;
279 }
280
281
282
283
284
285 public List<RefLeaseSpec> getRefLeaseSpecs() {
286 return new ArrayList<>(refLeaseSpecs.values());
287 }
288
289
290
291
292
293
294
295
296
297 public PushCommand setRefLeaseSpecs(RefLeaseSpec... specs) {
298 return setRefLeaseSpecs(Arrays.asList(specs));
299 }
300
301
302
303
304
305
306
307
308
309 public PushCommand setRefLeaseSpecs(List<RefLeaseSpec> specs) {
310 checkCallable();
311 this.refLeaseSpecs.clear();
312 for (RefLeaseSpec spec : specs) {
313 refLeaseSpecs.put(spec.getRef(), spec);
314 }
315 return this;
316 }
317
318
319
320
321 public List<RefSpec> getRefSpecs() {
322 return refSpecs;
323 }
324
325
326
327
328
329
330
331 public PushCommand setRefSpecs(RefSpec... specs) {
332 checkCallable();
333 this.refSpecs.clear();
334 Collections.addAll(refSpecs, specs);
335 return this;
336 }
337
338
339
340
341
342
343
344 public PushCommand setRefSpecs(List<RefSpec> specs) {
345 checkCallable();
346 this.refSpecs.clear();
347 this.refSpecs.addAll(specs);
348 return this;
349 }
350
351
352
353
354
355
356 public PushCommand setPushAll() {
357 refSpecs.add(Transport.REFSPEC_PUSH_ALL);
358 return this;
359 }
360
361
362
363
364
365
366 public PushCommand setPushTags() {
367 refSpecs.add(Transport.REFSPEC_TAGS);
368 return this;
369 }
370
371
372
373
374
375
376
377
378 public PushCommand add(Ref ref) {
379 refSpecs.add(new RefSpec(ref.getLeaf().getName()));
380 return this;
381 }
382
383
384
385
386
387
388
389
390
391
392 public PushCommand add(String nameOrSpec) {
393 if (0 <= nameOrSpec.indexOf(':')) {
394 refSpecs.add(new RefSpec(nameOrSpec));
395 } else {
396 Ref src;
397 try {
398 src = repo.findRef(nameOrSpec);
399 } catch (IOException e) {
400 throw new JGitInternalException(
401 JGitText.get().exceptionCaughtDuringExecutionOfPushCommand,
402 e);
403 }
404 if (src != null)
405 add(src);
406 }
407 return this;
408 }
409
410
411
412
413 public boolean isDryRun() {
414 return dryRun;
415 }
416
417
418
419
420
421
422
423 public PushCommand setDryRun(boolean dryRun) {
424 checkCallable();
425 this.dryRun = dryRun;
426 return this;
427 }
428
429
430
431
432 public boolean isThin() {
433 return thin;
434 }
435
436
437
438
439
440
441
442
443
444 public PushCommand setThin(boolean thin) {
445 checkCallable();
446 this.thin = thin;
447 return this;
448 }
449
450
451
452
453
454 public boolean isAtomic() {
455 return atomic;
456 }
457
458
459
460
461
462
463
464
465
466
467 public PushCommand setAtomic(boolean atomic) {
468 checkCallable();
469 this.atomic = atomic;
470 return this;
471 }
472
473
474
475
476 public boolean isForce() {
477 return force;
478 }
479
480
481
482
483
484
485
486 public PushCommand setForce(boolean force) {
487 checkCallable();
488 this.force = force;
489 return this;
490 }
491
492
493
494
495
496
497
498
499 public PushCommand setOutputStream(OutputStream out) {
500 this.out = out;
501 return this;
502 }
503
504
505
506
507
508 public List<String> getPushOptions() {
509 return pushOptions;
510 }
511
512
513
514
515
516
517
518
519 public PushCommand setPushOptions(List<String> pushOptions) {
520 this.pushOptions = pushOptions;
521 return this;
522 }
523 }