Capture non-progress side band #2 messages and put in result
[jgit/MarioXXX.git] / org.eclipse.jgit.pgm / src / org / eclipse / jgit / pgm / Push.java
blob2c025456393cb263f8450e303f8f8f9d420d8db3
1 /*
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
14 * conditions are met:
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
27 * written permission.
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")
65 int timeout = -1;
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) {
91 thin = false;
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;
105 @Override
106 protected void run() throws Exception {
107 if (force) {
108 final List<RefSpec> orig = new ArrayList<RefSpec>(refSpecs);
109 refSpecs.clear();
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) {
117 if (0 <= timeout)
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;
129 try {
130 result = transport.push(new TextProgressMonitor(), toPush);
131 } finally {
132 transport.close();
134 printPushResult(uri, result);
138 private void printPushResult(final URIish uri,
139 final PushResult result) {
140 shownURI = false;
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) {
146 if (verbose)
147 printRefUpdateResult(uri, result, rru);
148 } else
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) {
172 if (!shownURI) {
173 shownURI = true;
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()) {
181 case OK:
182 if (rru.isDelete())
183 printUpdateLine('-', "[deleted]", null, remoteName, null);
184 else {
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]";
190 else
191 summary = "[new branch]";
192 printUpdateLine('*', summary, srcRef, remoteName, null);
193 } else {
194 boolean fastForward = rru.isFastForward();
195 final char flag = fastForward ? ' ' : '+';
196 final String summary = oldRef.getObjectId().abbreviate(db)
197 .name()
198 + (fastForward ? ".." : "...")
199 + rru.getNewObjectId().abbreviate(db).name();
200 final String message = fastForward ? null : "forced update";
201 printUpdateLine(flag, summary, srcRef, remoteName, message);
204 break;
206 case NON_EXISTING:
207 printUpdateLine('X', "[no match]", null, remoteName, null);
208 break;
210 case REJECTED_NODELETE:
211 printUpdateLine('!', "[rejected]", null, remoteName,
212 "remote side does not support deleting refs");
213 break;
215 case REJECTED_NONFASTFORWARD:
216 printUpdateLine('!', "[rejected]", srcRef, remoteName,
217 "non-fast forward");
218 break;
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);
224 break;
226 case REJECTED_OTHER_REASON:
227 printUpdateLine('!', "[remote rejected]", srcRef, remoteName, rru
228 .getMessage());
229 break;
231 case UP_TO_DATE:
232 if (verbose)
233 printUpdateLine('=', "[up to date]", srcRef, remoteName, null);
234 break;
236 case NOT_ATTEMPTED:
237 case AWAITING_REPORT:
238 printUpdateLine('?', "[unexpected push-process behavior]", srcRef,
239 remoteName, rru.getMessage());
240 break;
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);
248 if (srcRef != null)
249 out.format(" %s ->", abbreviateRef(srcRef, true));
250 out.format(" %s", abbreviateRef(destRef, true));
252 if (message != null)
253 out.format(" (%s)", message);
255 out.println();