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