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
44
45 package org.eclipse.jgit.pgm;
46
47 import static java.lang.Character.valueOf;
48
49 import java.io.IOException;
50 import java.text.MessageFormat;
51 import java.util.ArrayList;
52 import java.util.List;
53
54 import org.eclipse.jgit.api.Git;
55 import org.eclipse.jgit.api.PushCommand;
56 import org.eclipse.jgit.api.errors.GitAPIException;
57 import org.eclipse.jgit.lib.Constants;
58 import org.eclipse.jgit.lib.ObjectId;
59 import org.eclipse.jgit.lib.ObjectReader;
60 import org.eclipse.jgit.lib.Ref;
61 import org.eclipse.jgit.lib.TextProgressMonitor;
62 import org.eclipse.jgit.pgm.internal.CLIText;
63 import org.eclipse.jgit.transport.PushResult;
64 import org.eclipse.jgit.transport.RefSpec;
65 import org.eclipse.jgit.transport.RemoteRefUpdate;
66 import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
67 import org.eclipse.jgit.transport.Transport;
68 import org.eclipse.jgit.transport.URIish;
69 import org.kohsuke.args4j.Argument;
70 import org.kohsuke.args4j.Option;
71
72 @Command(common = true, usage = "usage_UpdateRemoteRepositoryFromLocalRefs")
73 class Push extends TextBuiltin {
74 @Option(name = "--timeout", metaVar = "metaVar_seconds", usage = "usage_abortConnectionIfNoActivity")
75 int timeout = -1;
76
77 @Argument(index = 0, metaVar = "metaVar_uriish")
78 private String remote = Constants.DEFAULT_REMOTE_NAME;
79
80 @Argument(index = 1, metaVar = "metaVar_refspec")
81 private List<RefSpec> refSpecs = new ArrayList<>();
82
83 @Option(name = "--all")
84 private boolean all;
85
86 @Option(name = "--atomic")
87 private boolean atomic;
88
89 @Option(name = "--tags")
90 private boolean tags;
91
92 @Option(name = "--verbose", aliases = { "-v" })
93 private boolean verbose = false;
94
95 @Option(name = "--thin")
96 private boolean thin = Transport.DEFAULT_PUSH_THIN;
97
98 @Option(name = "--no-thin")
99 void nothin(@SuppressWarnings("unused") final boolean ignored) {
100 thin = false;
101 }
102
103 @Option(name = "--force", aliases = { "-f" })
104 private boolean force;
105
106 @Option(name = "--receive-pack", metaVar = "metaVar_path")
107 private String receivePack;
108
109 @Option(name = "--dry-run")
110 private boolean dryRun;
111
112 @Option(name = "--push-option", aliases = { "-t" })
113 private List<String> pushOptions = new ArrayList<>();
114
115 private boolean shownURI;
116
117
118 @Override
119 protected void run() {
120 try (Gitit.html#Git">Git git = new Git(db)) {
121 PushCommand push = git.push();
122 push.setDryRun(dryRun);
123 push.setForce(force);
124 push.setProgressMonitor(new TextProgressMonitor(errw));
125 push.setReceivePack(receivePack);
126 push.setRefSpecs(refSpecs);
127 if (all) {
128 push.setPushAll();
129 }
130 if (tags) {
131 push.setPushTags();
132 }
133 push.setRemote(remote);
134 push.setThin(thin);
135 push.setAtomic(atomic);
136 push.setTimeout(timeout);
137 if (!pushOptions.isEmpty()) {
138 push.setPushOptions(pushOptions);
139 }
140 Iterable<PushResult> results = push.call();
141 for (PushResult result : results) {
142 try (ObjectReader reader = db.newObjectReader()) {
143 printPushResult(reader, result.getURI(), result);
144 }
145 }
146 } catch (GitAPIException | IOException e) {
147 throw die(e.getMessage(), e);
148 }
149 }
150
151 private void printPushResult(final ObjectReader reader, final URIish uri,
152 final PushResult result) throws IOException {
153 shownURI = false;
154 boolean everythingUpToDate = true;
155
156
157 for (RemoteRefUpdate rru : result.getRemoteUpdates()) {
158 if (rru.getStatus() == Status.UP_TO_DATE) {
159 if (verbose)
160 printRefUpdateResult(reader, uri, result, rru);
161 } else
162 everythingUpToDate = false;
163 }
164
165 for (RemoteRefUpdate rru : result.getRemoteUpdates()) {
166
167 if (rru.getStatus() == Status.OK)
168 printRefUpdateResult(reader, uri, result, rru);
169 }
170
171 for (RemoteRefUpdate rru : result.getRemoteUpdates()) {
172
173 if (rru.getStatus() != Status.OK
174 && rru.getStatus() != Status.UP_TO_DATE)
175 printRefUpdateResult(reader, uri, result, rru);
176 }
177
178 AbstractFetchCommand.showRemoteMessages(errw, result.getMessages());
179 if (everythingUpToDate)
180 outw.println(CLIText.get().everythingUpToDate);
181 }
182
183 private void printRefUpdateResult(final ObjectReader reader,
184 final URIish uri, final PushResult result, final RemoteRefUpdate rru)
185 throws IOException {
186 if (!shownURI) {
187 shownURI = true;
188 outw.println(MessageFormat.format(CLIText.get().pushTo, uri));
189 }
190
191 final String remoteName = rru.getRemoteName();
192 final String srcRef = rru.isDelete() ? null : rru.getSrcRef();
193
194 switch (rru.getStatus()) {
195 case OK:
196 if (rru.isDelete())
197 printUpdateLine('-', "[deleted]", null, remoteName, null);
198 else {
199 final Ref oldRef = result.getAdvertisedRef(remoteName);
200 if (oldRef == null) {
201 final String summary;
202 if (remoteName.startsWith(Constants.R_TAGS))
203 summary = "[new tag]";
204 else
205 summary = "[new branch]";
206 printUpdateLine('*', summary, srcRef, remoteName, null);
207 } else {
208 boolean fastForward = rru.isFastForward();
209 final char flag = fastForward ? ' ' : '+';
210 final String summary = safeAbbreviate(reader, oldRef
211 .getObjectId())
212 + (fastForward ? ".." : "...")
213 + safeAbbreviate(reader, rru.getNewObjectId());
214 final String message = fastForward ? null : CLIText.get().forcedUpdate;
215 printUpdateLine(flag, summary, srcRef, remoteName, message);
216 }
217 }
218 break;
219
220 case NON_EXISTING:
221 printUpdateLine('X', "[no match]", null, remoteName, null);
222 break;
223
224 case REJECTED_NODELETE:
225 printUpdateLine('!', "[rejected]", null, remoteName,
226 CLIText.get().remoteSideDoesNotSupportDeletingRefs);
227 break;
228
229 case REJECTED_NONFASTFORWARD:
230 printUpdateLine('!', "[rejected]", srcRef, remoteName,
231 CLIText.get().nonFastForward);
232 break;
233
234 case REJECTED_REMOTE_CHANGED:
235 final String message = MessageFormat.format(
236 CLIText.get().remoteRefObjectChangedIsNotExpectedOne,
237 safeAbbreviate(reader, rru.getExpectedOldObjectId()));
238 printUpdateLine('!', "[rejected]", srcRef, remoteName, message);
239 break;
240
241 case REJECTED_OTHER_REASON:
242 printUpdateLine('!', "[remote rejected]", srcRef, remoteName, rru
243 .getMessage());
244 break;
245
246 case UP_TO_DATE:
247 if (verbose)
248 printUpdateLine('=', "[up to date]", srcRef, remoteName, null);
249 break;
250
251 case NOT_ATTEMPTED:
252 case AWAITING_REPORT:
253 printUpdateLine('?', "[unexpected push-process behavior]", srcRef,
254 remoteName, rru.getMessage());
255 break;
256 }
257 }
258
259 private static String safeAbbreviate(ObjectReader reader, ObjectId id) {
260 try {
261 return reader.abbreviate(id).name();
262 } catch (IOException cannotAbbreviate) {
263 return id.name();
264 }
265 }
266
267 private void printUpdateLine(final char flag, final String summary,
268 final String srcRef, final String destRef, final String message)
269 throws IOException {
270 outw.format(" %c %-17s", valueOf(flag), summary);
271
272 if (srcRef != null)
273 outw.format(" %s ->", abbreviateRef(srcRef, true));
274 outw.format(" %s", abbreviateRef(destRef, true));
275
276 if (message != null)
277 outw.format(" (%s)", message);
278
279 outw.println();
280 }
281 }