2 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
6 * Redistribution and use in source and binary forms, with or
7 * without modification, are permitted provided that the following
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * - Neither the name of the Git Development Community nor the
19 * names of its contributors may be used to endorse or promote
20 * products derived from this software without specific prior
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 package org
.spearce
.jgit
.pgm
;
40 import java
.util
.ArrayList
;
41 import java
.util
.Collection
;
42 import java
.util
.List
;
44 import org
.kohsuke
.args4j
.Argument
;
45 import org
.kohsuke
.args4j
.Option
;
46 import org
.spearce
.jgit
.lib
.Constants
;
47 import org
.spearce
.jgit
.lib
.Ref
;
48 import org
.spearce
.jgit
.lib
.TextProgressMonitor
;
49 import org
.spearce
.jgit
.transport
.PushResult
;
50 import org
.spearce
.jgit
.transport
.RefSpec
;
51 import org
.spearce
.jgit
.transport
.RemoteRefUpdate
;
52 import org
.spearce
.jgit
.transport
.Transport
;
53 import org
.spearce
.jgit
.transport
.URIish
;
54 import org
.spearce
.jgit
.transport
.RemoteRefUpdate
.Status
;
56 @Command(common
= true, usage
= "Update remote repository from local refs")
57 class Push
extends TextBuiltin
{
58 @Argument(index
= 0, metaVar
= "uri-ish")
59 private String remote
= "origin";
61 @Argument(index
= 1, metaVar
= "refspec")
62 private final List
<RefSpec
> refSpecs
= new ArrayList
<RefSpec
>();
64 @Option(name
= "--all")
65 void addAll(final boolean ignored
) {
66 refSpecs
.add(Transport
.REFSPEC_PUSH_ALL
);
69 @Option(name
= "--tags")
70 void addTags(final boolean ignored
) {
71 refSpecs
.add(Transport
.REFSPEC_TAGS
);
74 @Option(name
= "--verbose", aliases
= { "-v" })
75 private boolean verbose
= false;
77 @Option(name
= "--thin")
78 private boolean thin
= Transport
.DEFAULT_PUSH_THIN
;
80 @Option(name
= "--no-thin")
81 void nothin(final boolean ignored
) {
85 @Option(name
= "--force", aliases
= { "-f" })
86 private boolean force
;
88 @Option(name
= "--receive-pack", metaVar
= "path")
89 private String receivePack
;
91 @Option(name
= "--dry-run")
92 private boolean dryRun
;
94 private boolean shownURI
;
97 protected void run() throws Exception
{
99 final List
<RefSpec
> orig
= new ArrayList
<RefSpec
>(refSpecs
);
101 for (final RefSpec spec
: orig
)
102 refSpecs
.add(spec
.setForceUpdate(true));
105 final List
<Transport
> transports
= Transport
.openAll(db
, remote
);
106 for (final Transport transport
: transports
) {
107 transport
.setPushThin(thin
);
108 if (receivePack
!= null)
109 transport
.setOptionReceivePack(receivePack
);
110 transport
.setDryRun(dryRun
);
112 final Collection
<RemoteRefUpdate
> toPush
= transport
113 .findRemoteRefUpdatesFor(refSpecs
);
115 final URIish uri
= transport
.getURI();
116 final PushResult result
;
118 result
= transport
.push(new TextProgressMonitor(), toPush
);
122 printPushResult(uri
, result
);
126 private void printPushResult(final URIish uri
,
127 final PushResult result
) {
129 boolean everythingUpToDate
= true;
131 // at first, print up-to-date ones...
132 for (final RemoteRefUpdate rru
: result
.getRemoteUpdates()) {
133 if (rru
.getStatus() == Status
.UP_TO_DATE
) {
135 printRefUpdateResult(uri
, result
, rru
);
137 everythingUpToDate
= false;
140 for (final RemoteRefUpdate rru
: result
.getRemoteUpdates()) {
141 // ...then successful updates...
142 if (rru
.getStatus() == Status
.OK
)
143 printRefUpdateResult(uri
, result
, rru
);
146 for (final RemoteRefUpdate rru
: result
.getRemoteUpdates()) {
147 // ...finally, others (problematic)
148 if (rru
.getStatus() != Status
.OK
149 && rru
.getStatus() != Status
.UP_TO_DATE
)
150 printRefUpdateResult(uri
, result
, rru
);
153 if (everythingUpToDate
)
154 out
.println("Everything up-to-date");
157 private void printRefUpdateResult(final URIish uri
,
158 final PushResult result
, final RemoteRefUpdate rru
) {
161 out
.format("To %s\n", uri
);
164 final String remoteName
= rru
.getRemoteName();
165 final String srcRef
= rru
.isDelete() ?
null : rru
.getSrcRef();
167 switch (rru
.getStatus()) {
170 printUpdateLine('-', "[deleted]", null, remoteName
, null);
172 final Ref oldRef
= result
.getAdvertisedRef(remoteName
);
173 if (oldRef
== null) {
174 final String summary
;
175 if (remoteName
.startsWith(Constants
.R_TAGS
))
176 summary
= "[new tag]";
178 summary
= "[new branch]";
179 printUpdateLine('*', summary
, srcRef
, remoteName
, null);
181 boolean fastForward
= rru
.isFastForward();
182 final char flag
= fastForward ?
' ' : '+';
183 final String summary
= oldRef
.getObjectId().abbreviate(db
)
185 + (fastForward ?
".." : "...")
186 + rru
.getNewObjectId().abbreviate(db
).name();
187 final String message
= fastForward ?
null : "forced update";
188 printUpdateLine(flag
, summary
, srcRef
, remoteName
, message
);
194 printUpdateLine('X', "[no match]", null, remoteName
, null);
197 case REJECTED_NODELETE
:
198 printUpdateLine('!', "[rejected]", null, remoteName
,
199 "remote side does not support deleting refs");
202 case REJECTED_NONFASTFORWARD
:
203 printUpdateLine('!', "[rejected]", srcRef
, remoteName
,
207 case REJECTED_REMOTE_CHANGED
:
208 final String message
= "remote ref object changed - is not expected one "
209 + rru
.getExpectedOldObjectId().abbreviate(db
).name();
210 printUpdateLine('!', "[rejected]", srcRef
, remoteName
, message
);
213 case REJECTED_OTHER_REASON
:
214 printUpdateLine('!', "[remote rejected]", srcRef
, remoteName
, rru
220 printUpdateLine('=', "[up to date]", srcRef
, remoteName
, null);
224 case AWAITING_REPORT
:
225 printUpdateLine('?', "[unexpected push-process behavior]", srcRef
,
226 remoteName
, rru
.getMessage());
231 private void printUpdateLine(final char flag
, final String summary
,
232 final String srcRef
, final String destRef
, final String message
) {
233 out
.format(" %c %-17s", flag
, summary
);
236 out
.format(" %s ->", abbreviateRef(srcRef
, true));
237 out
.format(" %s", abbreviateRef(destRef
, true));
240 out
.format(" (%s)", message
);