2 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
3 * and other copyright owners as documented in the project's IP log.
5 * This program and the accompanying materials are made available
6 * under the terms of the Eclipse Distribution License v1.0 which
7 * accompanies this distribution, is reproduced below, and is
8 * available at http://www.eclipse.org/org/documents/edl-v10.php
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials provided
22 * with the distribution.
24 * - Neither the name of the Eclipse Foundation, Inc. nor the
25 * names of its contributors may be used to endorse or promote
26 * products derived from this software without specific prior
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44 package org
.eclipse
.jgit
.pgm
;
46 import java
.util
.ArrayList
;
47 import java
.util
.Collection
;
48 import java
.util
.List
;
50 import org
.kohsuke
.args4j
.Argument
;
51 import org
.kohsuke
.args4j
.Option
;
52 import org
.eclipse
.jgit
.lib
.Constants
;
53 import org
.eclipse
.jgit
.lib
.Ref
;
54 import org
.eclipse
.jgit
.lib
.TextProgressMonitor
;
55 import org
.eclipse
.jgit
.transport
.PushResult
;
56 import org
.eclipse
.jgit
.transport
.RefSpec
;
57 import org
.eclipse
.jgit
.transport
.RemoteRefUpdate
;
58 import org
.eclipse
.jgit
.transport
.Transport
;
59 import org
.eclipse
.jgit
.transport
.URIish
;
60 import org
.eclipse
.jgit
.transport
.RemoteRefUpdate
.Status
;
62 @Command(common
= true, usage
= "Update remote repository from local refs")
63 class Push
extends TextBuiltin
{
64 @Option(name
= "--timeout", metaVar
= "SECONDS", usage
= "abort connection if no activity")
67 @Argument(index
= 0, metaVar
= "uri-ish")
68 private String remote
= Constants
.DEFAULT_REMOTE_NAME
;
70 @Argument(index
= 1, metaVar
= "refspec")
71 private final List
<RefSpec
> refSpecs
= new ArrayList
<RefSpec
>();
73 @Option(name
= "--all")
74 void addAll(final boolean ignored
) {
75 refSpecs
.add(Transport
.REFSPEC_PUSH_ALL
);
78 @Option(name
= "--tags")
79 void addTags(final boolean ignored
) {
80 refSpecs
.add(Transport
.REFSPEC_TAGS
);
83 @Option(name
= "--verbose", aliases
= { "-v" })
84 private boolean verbose
= false;
86 @Option(name
= "--thin")
87 private boolean thin
= Transport
.DEFAULT_PUSH_THIN
;
89 @Option(name
= "--no-thin")
90 void nothin(final boolean ignored
) {
94 @Option(name
= "--force", aliases
= { "-f" })
95 private boolean force
;
97 @Option(name
= "--receive-pack", metaVar
= "path")
98 private String receivePack
;
100 @Option(name
= "--dry-run")
101 private boolean dryRun
;
103 private boolean shownURI
;
106 protected void run() throws Exception
{
108 final List
<RefSpec
> orig
= new ArrayList
<RefSpec
>(refSpecs
);
110 for (final RefSpec spec
: orig
)
111 refSpecs
.add(spec
.setForceUpdate(true));
114 final List
<Transport
> transports
;
115 transports
= Transport
.openAll(db
, remote
, Transport
.Operation
.PUSH
);
116 for (final Transport transport
: transports
) {
118 transport
.setTimeout(timeout
);
119 transport
.setPushThin(thin
);
120 if (receivePack
!= null)
121 transport
.setOptionReceivePack(receivePack
);
122 transport
.setDryRun(dryRun
);
124 final Collection
<RemoteRefUpdate
> toPush
= transport
125 .findRemoteRefUpdatesFor(refSpecs
);
127 final URIish uri
= transport
.getURI();
128 final PushResult result
;
130 result
= transport
.push(new TextProgressMonitor(), toPush
);
134 printPushResult(uri
, result
);
138 private void printPushResult(final URIish uri
,
139 final PushResult result
) {
141 boolean everythingUpToDate
= true;
143 // at first, print up-to-date ones...
144 for (final RemoteRefUpdate rru
: result
.getRemoteUpdates()) {
145 if (rru
.getStatus() == Status
.UP_TO_DATE
) {
147 printRefUpdateResult(uri
, result
, rru
);
149 everythingUpToDate
= false;
152 for (final RemoteRefUpdate rru
: result
.getRemoteUpdates()) {
153 // ...then successful updates...
154 if (rru
.getStatus() == Status
.OK
)
155 printRefUpdateResult(uri
, result
, rru
);
158 for (final RemoteRefUpdate rru
: result
.getRemoteUpdates()) {
159 // ...finally, others (problematic)
160 if (rru
.getStatus() != Status
.OK
161 && rru
.getStatus() != Status
.UP_TO_DATE
)
162 printRefUpdateResult(uri
, result
, rru
);
165 AbstractFetchCommand
.showRemoteMessages(result
.getMessages());
166 if (everythingUpToDate
)
167 out
.println("Everything up-to-date");
170 private void printRefUpdateResult(final URIish uri
,
171 final PushResult result
, final RemoteRefUpdate rru
) {
174 out
.format("To %s\n", uri
);
177 final String remoteName
= rru
.getRemoteName();
178 final String srcRef
= rru
.isDelete() ?
null : rru
.getSrcRef();
180 switch (rru
.getStatus()) {
183 printUpdateLine('-', "[deleted]", null, remoteName
, null);
185 final Ref oldRef
= result
.getAdvertisedRef(remoteName
);
186 if (oldRef
== null) {
187 final String summary
;
188 if (remoteName
.startsWith(Constants
.R_TAGS
))
189 summary
= "[new tag]";
191 summary
= "[new branch]";
192 printUpdateLine('*', summary
, srcRef
, remoteName
, null);
194 boolean fastForward
= rru
.isFastForward();
195 final char flag
= fastForward ?
' ' : '+';
196 final String summary
= oldRef
.getObjectId().abbreviate(db
)
198 + (fastForward ?
".." : "...")
199 + rru
.getNewObjectId().abbreviate(db
).name();
200 final String message
= fastForward ?
null : "forced update";
201 printUpdateLine(flag
, summary
, srcRef
, remoteName
, message
);
207 printUpdateLine('X', "[no match]", null, remoteName
, null);
210 case REJECTED_NODELETE
:
211 printUpdateLine('!', "[rejected]", null, remoteName
,
212 "remote side does not support deleting refs");
215 case REJECTED_NONFASTFORWARD
:
216 printUpdateLine('!', "[rejected]", srcRef
, remoteName
,
220 case REJECTED_REMOTE_CHANGED
:
221 final String message
= "remote ref object changed - is not expected one "
222 + rru
.getExpectedOldObjectId().abbreviate(db
).name();
223 printUpdateLine('!', "[rejected]", srcRef
, remoteName
, message
);
226 case REJECTED_OTHER_REASON
:
227 printUpdateLine('!', "[remote rejected]", srcRef
, remoteName
, rru
233 printUpdateLine('=', "[up to date]", srcRef
, remoteName
, null);
237 case AWAITING_REPORT
:
238 printUpdateLine('?', "[unexpected push-process behavior]", srcRef
,
239 remoteName
, rru
.getMessage());
244 private void printUpdateLine(final char flag
, final String summary
,
245 final String srcRef
, final String destRef
, final String message
) {
246 out
.format(" %c %-17s", flag
, summary
);
249 out
.format(" %s ->", abbreviateRef(srcRef
, true));
250 out
.format(" %s", abbreviateRef(destRef
, true));
253 out
.format(" (%s)", message
);