1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.api;
11
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16
17 import java.io.File;
18 import java.io.IOException;
19 import java.net.URISyntaxException;
20 import java.util.Properties;
21
22 import org.eclipse.jgit.api.errors.GitAPIException;
23 import org.eclipse.jgit.api.errors.JGitInternalException;
24 import org.eclipse.jgit.api.errors.TransportException;
25 import org.eclipse.jgit.errors.MissingObjectException;
26 import org.eclipse.jgit.hooks.PrePushHook;
27 import org.eclipse.jgit.junit.JGitTestUtil;
28 import org.eclipse.jgit.junit.RepositoryTestCase;
29 import org.eclipse.jgit.lib.ObjectId;
30 import org.eclipse.jgit.lib.Ref;
31 import org.eclipse.jgit.lib.RefUpdate;
32 import org.eclipse.jgit.lib.Repository;
33 import org.eclipse.jgit.lib.StoredConfig;
34 import org.eclipse.jgit.revwalk.RevCommit;
35 import org.eclipse.jgit.transport.PushResult;
36 import org.eclipse.jgit.transport.RefLeaseSpec;
37 import org.eclipse.jgit.transport.RefSpec;
38 import org.eclipse.jgit.transport.RemoteConfig;
39 import org.eclipse.jgit.transport.RemoteRefUpdate;
40 import org.eclipse.jgit.transport.TrackingRefUpdate;
41 import org.eclipse.jgit.transport.URIish;
42 import org.eclipse.jgit.util.FS;
43 import org.junit.Test;
44
45 public class PushCommandTest extends RepositoryTestCase {
46
47 @Test
48 public void testPush() throws JGitInternalException, IOException,
49 GitAPIException, URISyntaxException {
50
51
52 Repository db2 = createWorkRepository();
53 final StoredConfig config2 = db2.getConfig();
54
55
56 config2.setString("fsck", "", "missingEmail", "ignore");
57 config2.save();
58
59
60 final StoredConfig config = db.getConfig();
61 RemoteConfig remoteConfig = new RemoteConfig(config, "test");
62 URIish uri = new URIish(db2.getDirectory().toURI().toURL());
63 remoteConfig.addURI(uri);
64 remoteConfig.update(config);
65 config.save();
66
67 try (Git git1 = new Git(db)) {
68
69 RevCommit commit = git1.commit().setMessage("initial commit").call();
70 Ref tagRef = git1.tag().setName("tag").call();
71
72 try {
73 db2.resolve(commit.getId().getName() + "^{commit}");
74 fail("id shouldn't exist yet");
75 } catch (MissingObjectException e) {
76
77 }
78
79 RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x");
80 git1.push().setRemote("test").setRefSpecs(spec)
81 .call();
82
83 assertEquals(commit.getId(),
84 db2.resolve(commit.getId().getName() + "^{commit}"));
85 assertEquals(tagRef.getObjectId(),
86 db2.resolve(tagRef.getObjectId().getName()));
87 }
88 }
89
90 @Test
91 public void testPrePushHook() throws JGitInternalException, IOException,
92 GitAPIException, URISyntaxException {
93
94
95 Repository db2 = createWorkRepository();
96
97
98 final StoredConfig config = db.getConfig();
99 RemoteConfig remoteConfig = new RemoteConfig(config, "test");
100 URIish uri = new URIish(db2.getDirectory().toURI().toURL());
101 remoteConfig.addURI(uri);
102 remoteConfig.update(config);
103 config.save();
104
105 File hookOutput = new File(getTemporaryDirectory(), "hookOutput");
106 writeHookFile(PrePushHook.NAME, "#!/bin/sh\necho 1:$1, 2:$2, 3:$3 >\""
107 + hookOutput.toPath() + "\"\ncat - >>\"" + hookOutput.toPath()
108 + "\"\nexit 0");
109
110 try (Git git1 = new Git(db)) {
111
112 RevCommit commit = git1.commit().setMessage("initial commit").call();
113
114 RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x");
115 git1.push().setRemote("test").setRefSpecs(spec).call();
116 assertEquals("1:test, 2:" + uri + ", 3:\n" + "refs/heads/master "
117 + commit.getName() + " refs/heads/x "
118 + ObjectId.zeroId().name() + "\n", read(hookOutput));
119 }
120 }
121
122 private File writeHookFile(String name, String data)
123 throws IOException {
124 File path = new File(db.getWorkTree() + "/.git/hooks/", name);
125 JGitTestUtil.write(path, data);
126 FS.DETECTED.setExecute(path, true);
127 return path;
128 }
129
130
131 @Test
132 public void testTrackingUpdate() throws Exception {
133 Repository db2 = createBareRepository();
134
135 String remote = "origin";
136 String branch = "refs/heads/master";
137 String trackingBranch = "refs/remotes/" + remote + "/master";
138
139 try (Git git = new Git(db)) {
140 RevCommit commit1 = git.commit().setMessage("Initial commit")
141 .call();
142
143 RefUpdate branchRefUpdate = db.updateRef(branch);
144 branchRefUpdate.setNewObjectId(commit1.getId());
145 branchRefUpdate.update();
146
147 RefUpdate trackingBranchRefUpdate = db.updateRef(trackingBranch);
148 trackingBranchRefUpdate.setNewObjectId(commit1.getId());
149 trackingBranchRefUpdate.update();
150
151 final StoredConfig config = db.getConfig();
152 RemoteConfig remoteConfig = new RemoteConfig(config, remote);
153 URIish uri = new URIish(db2.getDirectory().toURI().toURL());
154 remoteConfig.addURI(uri);
155 remoteConfig.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/"
156 + remote + "/*"));
157 remoteConfig.update(config);
158 config.save();
159
160
161 RevCommit commit2 = git.commit().setMessage("Commit to push").call();
162
163 RefSpec spec = new RefSpec(branch + ":" + branch);
164 Iterable<PushResult> resultIterable = git.push().setRemote(remote)
165 .setRefSpecs(spec).call();
166
167 PushResult result = resultIterable.iterator().next();
168 TrackingRefUpdate trackingRefUpdate = result
169 .getTrackingRefUpdate(trackingBranch);
170
171 assertNotNull(trackingRefUpdate);
172 assertEquals(trackingBranch, trackingRefUpdate.getLocalName());
173 assertEquals(branch, trackingRefUpdate.getRemoteName());
174 assertEquals(commit2.getId(), trackingRefUpdate.getNewObjectId());
175 assertEquals(commit2.getId(), db.resolve(trackingBranch));
176 assertEquals(commit2.getId(), db2.resolve(branch));
177 }
178 }
179
180
181
182
183
184
185 @Test
186 public void testPushRefUpdate() throws Exception {
187 try (Git git = new Git(db);
188 Git git2 = new Git(createBareRepository())) {
189 final StoredConfig config = git.getRepository().getConfig();
190 RemoteConfig remoteConfig = new RemoteConfig(config, "test");
191 URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
192 .toURL());
193 remoteConfig.addURI(uri);
194 remoteConfig.addPushRefSpec(new RefSpec("+refs/heads/*:refs/heads/*"));
195 remoteConfig.update(config);
196 config.save();
197
198 writeTrashFile("f", "content of f");
199 git.add().addFilepattern("f").call();
200 RevCommit commit = git.commit().setMessage("adding f").call();
201
202 assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
203 git.push().setRemote("test").call();
204 assertEquals(commit.getId(),
205 git2.getRepository().resolve("refs/heads/master"));
206
207 git.branchCreate().setName("refs/heads/test").call();
208 git.checkout().setName("refs/heads/test").call();
209
210 for (int i = 0; i < 6; i++) {
211 writeTrashFile("f" + i, "content of f" + i);
212 git.add().addFilepattern("f" + i).call();
213 commit = git.commit().setMessage("adding f" + i).call();
214 git.push().setRemote("test").call();
215 git2.getRepository().getRefDatabase().getRefs();
216 assertEquals("failed to update on attempt " + i, commit.getId(),
217 git2.getRepository().resolve("refs/heads/test"));
218 }
219 }
220 }
221
222
223
224
225
226
227 @Test
228 public void testPushWithRefSpecFromConfig() throws Exception {
229 try (Git git = new Git(db);
230 Git git2 = new Git(createBareRepository())) {
231 final StoredConfig config = git.getRepository().getConfig();
232 RemoteConfig remoteConfig = new RemoteConfig(config, "test");
233 URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
234 .toURL());
235 remoteConfig.addURI(uri);
236 remoteConfig.addPushRefSpec(new RefSpec("HEAD:refs/heads/newbranch"));
237 remoteConfig.update(config);
238 config.save();
239
240 writeTrashFile("f", "content of f");
241 git.add().addFilepattern("f").call();
242 RevCommit commit = git.commit().setMessage("adding f").call();
243
244 assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
245 git.push().setRemote("test").call();
246 assertEquals(commit.getId(),
247 git2.getRepository().resolve("refs/heads/newbranch"));
248 }
249 }
250
251
252
253
254
255
256 @Test
257 public void testPushWithoutPushRefSpec() throws Exception {
258 try (Git git = new Git(db);
259 Git git2 = new Git(createBareRepository())) {
260 final StoredConfig config = git.getRepository().getConfig();
261 RemoteConfig remoteConfig = new RemoteConfig(config, "test");
262 URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
263 .toURL());
264 remoteConfig.addURI(uri);
265 remoteConfig.addFetchRefSpec(new RefSpec(
266 "+refs/heads/*:refs/remotes/origin/*"));
267 remoteConfig.update(config);
268 config.save();
269
270 writeTrashFile("f", "content of f");
271 git.add().addFilepattern("f").call();
272 RevCommit commit = git.commit().setMessage("adding f").call();
273
274 git.checkout().setName("not-pushed").setCreateBranch(true).call();
275 git.checkout().setName("branchtopush").setCreateBranch(true).call();
276
277 assertEquals(null,
278 git2.getRepository().resolve("refs/heads/branchtopush"));
279 assertEquals(null, git2.getRepository()
280 .resolve("refs/heads/not-pushed"));
281 assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
282 git.push().setRemote("test").call();
283 assertEquals(commit.getId(),
284 git2.getRepository().resolve("refs/heads/branchtopush"));
285 assertEquals(null, git2.getRepository()
286 .resolve("refs/heads/not-pushed"));
287 assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
288 }
289 }
290
291
292
293
294
295
296 @Test
297 public void testPushAfterGC() throws Exception {
298
299 Repository db2 = createWorkRepository();
300
301
302 final StoredConfig config = db.getConfig();
303 RemoteConfig remoteConfig = new RemoteConfig(config, "test");
304 URIish uri = new URIish(db2.getDirectory().toURI().toURL());
305 remoteConfig.addURI(uri);
306 remoteConfig.update(config);
307 config.save();
308
309 try (Git git1 = new Git(db);
310 Git git2 = new Git(db2)) {
311
312 git1.commit().setMessage("initial commit").call();
313
314 RefSpec spec = new RefSpec("refs/heads/*:refs/heads/*");
315 git1.push().setRemote("test").setRefSpecs(spec).call();
316
317
318 git2.branchCreate().setName("refs/heads/other").call();
319 git2.checkout().setName("refs/heads/other").call();
320
321 writeTrashFile("a", "content of a");
322 git2.add().addFilepattern("a").call();
323 RevCommit commit2 = git2.commit().setMessage("adding a").call();
324
325
326 Properties res = git1.gc().setExpire(null).call();
327 assertEquals(7, res.size());
328
329
330 writeTrashFile("b", "content of b");
331 git1.add().addFilepattern("b").call();
332 RevCommit commit3 = git1.commit().setMessage("adding b").call();
333
334 try {
335
336 git1.push().setRemote("test").setRefSpecs(spec).call();
337 } catch (TransportException e) {
338 assertTrue("should be caused by a MissingObjectException", e
339 .getCause().getCause() instanceof MissingObjectException);
340 fail("caught MissingObjectException for a change we don't have");
341 }
342
343
344 try {
345 db.resolve(commit2.getId().getName() + "^{commit}");
346 fail("id shouldn't exist locally");
347 } catch (MissingObjectException e) {
348
349 }
350 assertEquals(commit2.getId(),
351 db2.resolve(commit2.getId().getName() + "^{commit}"));
352 assertEquals(commit3.getId(),
353 db2.resolve(commit3.getId().getName() + "^{commit}"));
354 }
355 }
356
357 @Test
358 public void testPushWithLease() throws JGitInternalException, IOException,
359 GitAPIException, URISyntaxException {
360
361
362 Repository db2 = createWorkRepository();
363
364
365 final StoredConfig config = db.getConfig();
366 RemoteConfig remoteConfig = new RemoteConfig(config, "test");
367 URIish uri = new URIish(db2.getDirectory().toURI().toURL());
368 remoteConfig.addURI(uri);
369 remoteConfig.update(config);
370 config.save();
371
372 try (Git git1 = new Git(db)) {
373
374 RevCommit commit = git1.commit().setMessage("initial commit").call();
375 git1.branchCreate().setName("initial").call();
376
377 RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x");
378 git1.push().setRemote("test").setRefSpecs(spec)
379 .call();
380
381 assertEquals(commit.getId(),
382 db2.resolve(commit.getId().getName() + "^{commit}"));
383
384
385 git1.commit().setMessage("second commit").call();
386 Iterable<PushResult> results =
387 git1.push().setRemote("test").setRefSpecs(spec)
388 .setRefLeaseSpecs(new RefLeaseSpec("refs/heads/x", "initial"))
389 .call();
390 for (PushResult result : results) {
391 RemoteRefUpdate update = result.getRemoteUpdate("refs/heads/x");
392 assertEquals(update.getStatus(), RemoteRefUpdate.Status.OK);
393 }
394
395 git1.commit().setMessage("third commit").call();
396
397
398 results =
399 git1.push().setRemote("test").setRefSpecs(spec)
400 .setRefLeaseSpecs(new RefLeaseSpec("refs/heads/x", "initial"))
401 .call();
402 for (PushResult result : results) {
403 RemoteRefUpdate update = result.getRemoteUpdate("refs/heads/x");
404 assertEquals(update.getStatus(), RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED);
405 }
406 }
407 }
408 }