View Javadoc
1   /*
2    * Copyright (C) 2010, 2014 Chris Aniszczyk <caniszczyk@gmail.com> and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.api;
11  
12  import static org.junit.Assert.assertEquals;
13  import static org.junit.Assert.assertFalse;
14  import static org.junit.Assert.assertNotNull;
15  import static org.junit.Assert.assertThrows;
16  import static org.junit.Assert.assertTrue;
17  import static org.junit.Assert.fail;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.net.URISyntaxException;
22  import java.util.Properties;
23  
24  import org.eclipse.jgit.api.errors.DetachedHeadException;
25  import org.eclipse.jgit.api.errors.GitAPIException;
26  import org.eclipse.jgit.api.errors.InvalidRefNameException;
27  import org.eclipse.jgit.api.errors.JGitInternalException;
28  import org.eclipse.jgit.api.errors.TransportException;
29  import org.eclipse.jgit.errors.MissingObjectException;
30  import org.eclipse.jgit.errors.NoRemoteRepositoryException;
31  import org.eclipse.jgit.hooks.PrePushHook;
32  import org.eclipse.jgit.junit.JGitTestUtil;
33  import org.eclipse.jgit.junit.RepositoryTestCase;
34  import org.eclipse.jgit.lib.ObjectId;
35  import org.eclipse.jgit.lib.Ref;
36  import org.eclipse.jgit.lib.RefUpdate;
37  import org.eclipse.jgit.lib.Repository;
38  import org.eclipse.jgit.lib.StoredConfig;
39  import org.eclipse.jgit.revwalk.RevCommit;
40  import org.eclipse.jgit.transport.PushConfig.PushDefault;
41  import org.eclipse.jgit.transport.PushResult;
42  import org.eclipse.jgit.transport.RefLeaseSpec;
43  import org.eclipse.jgit.transport.RefSpec;
44  import org.eclipse.jgit.transport.RemoteConfig;
45  import org.eclipse.jgit.transport.RemoteRefUpdate;
46  import org.eclipse.jgit.transport.TrackingRefUpdate;
47  import org.eclipse.jgit.transport.URIish;
48  import org.eclipse.jgit.util.FS;
49  import org.junit.Test;
50  
51  public class PushCommandTest extends RepositoryTestCase {
52  
53  	@Test
54  	public void testPush() throws JGitInternalException, IOException,
55  			GitAPIException, URISyntaxException {
56  
57  		// create other repository
58  		Repository db2 = createWorkRepository();
59  		addRepoToClose(db2);
60  		final StoredConfig config2 = db2.getConfig();
61  
62  		// this tests that this config can be parsed properly
63  		config2.setString("fsck", "", "missingEmail", "ignore");
64  		config2.save();
65  
66  		// setup the first repository
67  		final StoredConfig config = db.getConfig();
68  		RemoteConfig remoteConfig = new RemoteConfig(config, "test");
69  		URIish uri = new URIish(db2.getDirectory().toURI().toURL());
70  		remoteConfig.addURI(uri);
71  		remoteConfig.update(config);
72  		config.save();
73  
74  		try (Git git1 = new Git(db)) {
75  			// create some refs via commits and tag
76  			RevCommit commit = git1.commit().setMessage("initial commit").call();
77  			Ref tagRef = git1.tag().setName("tag").call();
78  
79  			try {
80  				db2.resolve(commit.getId().getName() + "^{commit}");
81  				fail("id shouldn't exist yet");
82  			} catch (MissingObjectException e) {
83  				// we should get here
84  			}
85  
86  			RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x");
87  			git1.push().setRemote("test").setRefSpecs(spec)
88  					.call();
89  
90  			assertEquals(commit.getId(),
91  					db2.resolve(commit.getId().getName() + "^{commit}"));
92  			assertEquals(tagRef.getObjectId(),
93  					db2.resolve(tagRef.getObjectId().getName()));
94  		}
95  	}
96  
97  	@Test
98  	public void testPrePushHook() throws JGitInternalException, IOException,
99  			GitAPIException, URISyntaxException {
100 
101 		// create other repository
102 		Repository db2 = createWorkRepository();
103 
104 		// setup the first repository
105 		final StoredConfig config = db.getConfig();
106 		RemoteConfig remoteConfig = new RemoteConfig(config, "test");
107 		URIish uri = new URIish(db2.getDirectory().toURI().toURL());
108 		remoteConfig.addURI(uri);
109 		remoteConfig.update(config);
110 		config.save();
111 
112 		File hookOutput = new File(getTemporaryDirectory(), "hookOutput");
113 		writeHookFile(PrePushHook.NAME, "#!/bin/sh\necho 1:$1, 2:$2, 3:$3 >\""
114 				+ hookOutput.toPath() + "\"\ncat - >>\"" + hookOutput.toPath()
115 				+ "\"\nexit 0");
116 
117 		try (Git git1 = new Git(db)) {
118 			// create some refs via commits and tag
119 			RevCommit commit = git1.commit().setMessage("initial commit").call();
120 
121 			RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x");
122 			git1.push().setRemote("test").setRefSpecs(spec).call();
123 			assertEquals("1:test, 2:" + uri + ", 3:\n" + "refs/heads/master "
124 					+ commit.getName() + " refs/heads/x "
125 					+ ObjectId.zeroId().name() + "\n", read(hookOutput));
126 		}
127 	}
128 
129 	private File writeHookFile(String name, String data)
130 			throws IOException {
131 		File path = new File(db.getWorkTree() + "/.git/hooks/", name);
132 		JGitTestUtil.write(path, data);
133 		FS.DETECTED.setExecute(path, true);
134 		return path;
135 	}
136 
137 
138 	@Test
139 	public void testTrackingUpdate() throws Exception {
140 		Repository db2 = createBareRepository();
141 
142 		String remote = "origin";
143 		String branch = "refs/heads/master";
144 		String trackingBranch = "refs/remotes/" + remote + "/master";
145 
146 		try (Git git = new Git(db)) {
147 			RevCommit commit1 = git.commit().setMessage("Initial commit")
148 					.call();
149 
150 			RefUpdate branchRefUpdate = db.updateRef(branch);
151 			branchRefUpdate.setNewObjectId(commit1.getId());
152 			branchRefUpdate.update();
153 
154 			RefUpdate trackingBranchRefUpdate = db.updateRef(trackingBranch);
155 			trackingBranchRefUpdate.setNewObjectId(commit1.getId());
156 			trackingBranchRefUpdate.update();
157 
158 			final StoredConfig config = db.getConfig();
159 			RemoteConfig remoteConfig = new RemoteConfig(config, remote);
160 			URIish uri = new URIish(db2.getDirectory().toURI().toURL());
161 			remoteConfig.addURI(uri);
162 			remoteConfig.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/"
163 					+ remote + "/*"));
164 			remoteConfig.update(config);
165 			config.save();
166 
167 
168 			RevCommit commit2 = git.commit().setMessage("Commit to push").call();
169 
170 			RefSpec spec = new RefSpec(branch + ":" + branch);
171 			Iterable<PushResult> resultIterable = git.push().setRemote(remote)
172 					.setRefSpecs(spec).call();
173 
174 			PushResult result = resultIterable.iterator().next();
175 			TrackingRefUpdate trackingRefUpdate = result
176 					.getTrackingRefUpdate(trackingBranch);
177 
178 			assertNotNull(trackingRefUpdate);
179 			assertEquals(trackingBranch, trackingRefUpdate.getLocalName());
180 			assertEquals(branch, trackingRefUpdate.getRemoteName());
181 			assertEquals(commit2.getId(), trackingRefUpdate.getNewObjectId());
182 			assertEquals(commit2.getId(), db.resolve(trackingBranch));
183 			assertEquals(commit2.getId(), db2.resolve(branch));
184 		}
185 	}
186 
187 	/**
188 	 * Check that pushes over file protocol lead to appropriate ref-updates.
189 	 *
190 	 * @throws Exception
191 	 */
192 	@Test
193 	public void testPushRefUpdate() throws Exception {
194 		try (Git git = new Git(db);
195 				Git git2 = new Git(createBareRepository())) {
196 			final StoredConfig config = git.getRepository().getConfig();
197 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
198 			URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
199 					.toURL());
200 			remoteConfig.addURI(uri);
201 			remoteConfig.addPushRefSpec(new RefSpec("+refs/heads/*:refs/heads/*"));
202 			remoteConfig.update(config);
203 			config.save();
204 
205 			writeTrashFile("f", "content of f");
206 			git.add().addFilepattern("f").call();
207 			RevCommit commit = git.commit().setMessage("adding f").call();
208 
209 			assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
210 			git.push().setRemote("test").call();
211 			assertEquals(commit.getId(),
212 					git2.getRepository().resolve("refs/heads/master"));
213 
214 			git.branchCreate().setName("refs/heads/test").call();
215 			git.checkout().setName("refs/heads/test").call();
216 
217 			for (int i = 0; i < 6; i++) {
218 				writeTrashFile("f" + i, "content of f" + i);
219 				git.add().addFilepattern("f" + i).call();
220 				commit = git.commit().setMessage("adding f" + i).call();
221 				git.push().setRemote("test").call();
222 				git2.getRepository().getRefDatabase().getRefs();
223 				assertEquals("failed to update on attempt " + i, commit.getId(),
224 						git2.getRepository().resolve("refs/heads/test"));
225 			}
226 		}
227 	}
228 
229 	/**
230 	 * Check that the push refspec is read from config.
231 	 *
232 	 * @throws Exception
233 	 */
234 	@Test
235 	public void testPushWithRefSpecFromConfig() throws Exception {
236 		try (Git git = new Git(db);
237 				Git git2 = new Git(createBareRepository())) {
238 			final StoredConfig config = git.getRepository().getConfig();
239 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
240 			URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
241 					.toURL());
242 			remoteConfig.addURI(uri);
243 			remoteConfig.addPushRefSpec(new RefSpec("HEAD:refs/heads/newbranch"));
244 			remoteConfig.update(config);
245 			config.save();
246 
247 			writeTrashFile("f", "content of f");
248 			git.add().addFilepattern("f").call();
249 			RevCommit commit = git.commit().setMessage("adding f").call();
250 
251 			assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
252 			git.push().setRemote("test").call();
253 			assertEquals(commit.getId(),
254 					git2.getRepository().resolve("refs/heads/newbranch"));
255 		}
256 	}
257 
258 	/**
259 	 * Check that only HEAD is pushed if no refspec is given.
260 	 *
261 	 * @throws Exception
262 	 */
263 	@Test
264 	public void testPushWithoutPushRefSpec() throws Exception {
265 		try (Git git = new Git(db);
266 				Git git2 = new Git(createBareRepository())) {
267 			final StoredConfig config = git.getRepository().getConfig();
268 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
269 			URIish uri = new URIish(git2.getRepository().getDirectory().toURI()
270 					.toURL());
271 			remoteConfig.addURI(uri);
272 			remoteConfig.addFetchRefSpec(new RefSpec(
273 					"+refs/heads/*:refs/remotes/origin/*"));
274 			remoteConfig.update(config);
275 			config.save();
276 
277 			writeTrashFile("f", "content of f");
278 			git.add().addFilepattern("f").call();
279 			RevCommit commit = git.commit().setMessage("adding f").call();
280 
281 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
282 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
283 
284 			assertEquals(null,
285 					git2.getRepository().resolve("refs/heads/branchtopush"));
286 			assertEquals(null, git2.getRepository()
287 					.resolve("refs/heads/not-pushed"));
288 			assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
289 			git.push().setRemote("test").call();
290 			assertEquals(commit.getId(),
291 					git2.getRepository().resolve("refs/heads/branchtopush"));
292 			assertEquals(null, git2.getRepository()
293 					.resolve("refs/heads/not-pushed"));
294 			assertEquals(null, git2.getRepository().resolve("refs/heads/master"));
295 		}
296 	}
297 
298 	/**
299 	 * Check that pushing from a detached HEAD without refspec throws a
300 	 * DetachedHeadException.
301 	 *
302 	 * @throws Exception
303 	 */
304 	@Test
305 	public void testPushDefaultDetachedHead() throws Exception {
306 		try (Git git = new Git(db);
307 				Git git2 = new Git(createBareRepository())) {
308 			final StoredConfig config = git.getRepository().getConfig();
309 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
310 			URIish uri = new URIish(
311 					git2.getRepository().getDirectory().toURI().toURL());
312 			remoteConfig.addURI(uri);
313 			remoteConfig.addFetchRefSpec(
314 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
315 			remoteConfig.update(config);
316 			config.save();
317 
318 			writeTrashFile("f", "content of f");
319 			git.add().addFilepattern("f").call();
320 			RevCommit commit = git.commit().setMessage("adding f").call();
321 
322 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
323 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
324 			git.checkout().setName(commit.getName()).call();
325 			String head = git.getRepository().getFullBranch();
326 			assertTrue(ObjectId.isId(head));
327 			assertEquals(commit.getName(), head);
328 			assertThrows(DetachedHeadException.class,
329 					() -> git.push().setRemote("test").call());
330 		}
331 	}
332 
333 	/**
334 	 * Check that push.default=nothing without refspec throws an
335 	 * InvalidRefNameException.
336 	 *
337 	 * @throws Exception
338 	 */
339 	@Test
340 	public void testPushDefaultNothing() throws Exception {
341 		try (Git git = new Git(db);
342 				Git git2 = new Git(createBareRepository())) {
343 			final StoredConfig config = git.getRepository().getConfig();
344 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
345 			URIish uri = new URIish(
346 					git2.getRepository().getDirectory().toURI().toURL());
347 			remoteConfig.addURI(uri);
348 			remoteConfig.addFetchRefSpec(
349 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
350 			remoteConfig.update(config);
351 			config.save();
352 
353 			writeTrashFile("f", "content of f");
354 			git.add().addFilepattern("f").call();
355 			git.commit().setMessage("adding f").call();
356 
357 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
358 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
359 
360 			assertEquals(null,
361 					git2.getRepository().resolve("refs/heads/branchtopush"));
362 			assertEquals(null,
363 					git2.getRepository().resolve("refs/heads/not-pushed"));
364 			assertEquals(null,
365 					git2.getRepository().resolve("refs/heads/master"));
366 			assertThrows(InvalidRefNameException.class,
367 					() -> git.push().setRemote("test")
368 							.setPushDefault(PushDefault.NOTHING).call());
369 		}
370 	}
371 
372 	/**
373 	 * Check that push.default=matching without refspec pushes all matching
374 	 * branches.
375 	 *
376 	 * @throws Exception
377 	 */
378 	@Test
379 	public void testPushDefaultMatching() throws Exception {
380 		try (Git git = new Git(db);
381 				Git git2 = new Git(createBareRepository())) {
382 			final StoredConfig config = git.getRepository().getConfig();
383 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
384 			URIish uri = new URIish(
385 					git2.getRepository().getDirectory().toURI().toURL());
386 			remoteConfig.addURI(uri);
387 			remoteConfig.addFetchRefSpec(
388 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
389 			remoteConfig.update(config);
390 			config.save();
391 
392 			writeTrashFile("f", "content of f");
393 			git.add().addFilepattern("f").call();
394 			RevCommit commit = git.commit().setMessage("adding f").call();
395 
396 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
397 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
398 
399 			assertEquals(null,
400 					git2.getRepository().resolve("refs/heads/branchtopush"));
401 			assertEquals(null,
402 					git2.getRepository().resolve("refs/heads/not-pushed"));
403 			assertEquals(null,
404 					git2.getRepository().resolve("refs/heads/master"));
405 			// push master and branchtopush
406 			git.push().setRemote("test").setRefSpecs(
407 					new RefSpec("refs/heads/master:refs/heads/master"),
408 					new RefSpec(
409 							"refs/heads/branchtopush:refs/heads/branchtopush"))
410 					.call();
411 			assertEquals(commit.getId(),
412 					git2.getRepository().resolve("refs/heads/master"));
413 			assertEquals(commit.getId(),
414 					git2.getRepository().resolve("refs/heads/branchtopush"));
415 			assertEquals(null,
416 					git2.getRepository().resolve("refs/heads/not-pushed"));
417 			// Create two different commits on these two branches
418 			writeTrashFile("b", "on branchtopush");
419 			git.add().addFilepattern("b").call();
420 			RevCommit bCommit = git.commit().setMessage("on branchtopush")
421 					.call();
422 			git.checkout().setName("master").call();
423 			writeTrashFile("m", "on master");
424 			git.add().addFilepattern("m").call();
425 			RevCommit mCommit = git.commit().setMessage("on master").call();
426 			// Now push with mode "matching": should push both branches.
427 			Iterable<PushResult> result = git.push().setRemote("test")
428 					.setPushDefault(PushDefault.MATCHING)
429 					.call();
430 			int n = 0;
431 			for (PushResult r : result) {
432 				n++;
433 				assertEquals(1, n);
434 				assertEquals(2, r.getRemoteUpdates().size());
435 				for (RemoteRefUpdate update : r.getRemoteUpdates()) {
436 					assertFalse(update.isMatching());
437 					assertTrue(update.getSrcRef()
438 							.equals("refs/heads/branchtopush")
439 							|| update.getSrcRef().equals("refs/heads/master"));
440 					assertEquals(RemoteRefUpdate.Status.OK, update.getStatus());
441 				}
442 			}
443 			assertEquals(bCommit.getId(),
444 					git2.getRepository().resolve("refs/heads/branchtopush"));
445 			assertEquals(null,
446 					git2.getRepository().resolve("refs/heads/not-pushed"));
447 			assertEquals(mCommit.getId(),
448 					git2.getRepository().resolve("refs/heads/master"));
449 			assertEquals(bCommit.getId(), git.getRepository()
450 					.resolve("refs/remotes/origin/branchtopush"));
451 			assertEquals(null, git.getRepository()
452 					.resolve("refs/remotes/origin/not-pushed"));
453 			assertEquals(mCommit.getId(),
454 					git.getRepository().resolve("refs/remotes/origin/master"));
455 		}
456 	}
457 
458 	/**
459 	 * Check that push.default=upstream without refspec pushes only the current
460 	 * branch to the configured upstream.
461 	 *
462 	 * @throws Exception
463 	 */
464 	@Test
465 	public void testPushDefaultUpstream() throws Exception {
466 		try (Git git = new Git(db);
467 				Git git2 = new Git(createBareRepository())) {
468 			StoredConfig config = git.getRepository().getConfig();
469 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
470 			URIish uri = new URIish(
471 					git2.getRepository().getDirectory().toURI().toURL());
472 			remoteConfig.addURI(uri);
473 			remoteConfig.addFetchRefSpec(
474 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
475 			remoteConfig.update(config);
476 			config.save();
477 
478 			writeTrashFile("f", "content of f");
479 			git.add().addFilepattern("f").call();
480 			RevCommit commit = git.commit().setMessage("adding f").call();
481 
482 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
483 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
484 
485 			config = git.getRepository().getConfig();
486 			config.setString("branch", "branchtopush", "remote", "test");
487 			config.setString("branch", "branchtopush", "merge",
488 					"refs/heads/upstreambranch");
489 			config.save();
490 
491 			assertEquals(null,
492 					git2.getRepository().resolve("refs/heads/branchtopush"));
493 			assertEquals(null,
494 					git2.getRepository().resolve("refs/heads/upstreambranch"));
495 			assertEquals(null,
496 					git2.getRepository().resolve("refs/heads/not-pushed"));
497 			assertEquals(null,
498 					git2.getRepository().resolve("refs/heads/master"));
499 			git.push().setRemote("test").setPushDefault(PushDefault.UPSTREAM)
500 					.call();
501 			assertEquals(null,
502 					git2.getRepository().resolve("refs/heads/branchtopush"));
503 			assertEquals(commit.getId(),
504 					git2.getRepository().resolve("refs/heads/upstreambranch"));
505 			assertEquals(null,
506 					git2.getRepository().resolve("refs/heads/not-pushed"));
507 			assertEquals(null,
508 					git2.getRepository().resolve("refs/heads/master"));
509 			assertEquals(commit.getId(), git.getRepository()
510 					.resolve("refs/remotes/origin/upstreambranch"));
511 			assertEquals(null, git.getRepository()
512 					.resolve("refs/remotes/origin/branchtopush"));
513 		}
514 	}
515 
516 	/**
517 	 * Check that push.default=upstream without refspec throws an
518 	 * InvalidRefNameException if the current branch has no upstream.
519 	 *
520 	 * @throws Exception
521 	 */
522 	@Test
523 	public void testPushDefaultUpstreamNoTracking() throws Exception {
524 		try (Git git = new Git(db);
525 				Git git2 = new Git(createBareRepository())) {
526 			StoredConfig config = git.getRepository().getConfig();
527 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
528 			URIish uri = new URIish(
529 					git2.getRepository().getDirectory().toURI().toURL());
530 			remoteConfig.addURI(uri);
531 			remoteConfig.addFetchRefSpec(
532 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
533 			remoteConfig.update(config);
534 			config.save();
535 
536 			writeTrashFile("f", "content of f");
537 			git.add().addFilepattern("f").call();
538 			git.commit().setMessage("adding f").call();
539 
540 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
541 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
542 
543 			config = git.getRepository().getConfig();
544 			config.setString("branch", "branchtopush", "remote", "test");
545 			config.save();
546 
547 			assertThrows(InvalidRefNameException.class,
548 					() -> git.push().setRemote("test")
549 							.setPushDefault(PushDefault.UPSTREAM).call());
550 		}
551 	}
552 
553 	/**
554 	 * Check that push.default=upstream without refspec throws an
555 	 * InvalidRefNameException if the push remote is not the same as the fetch
556 	 * remote.
557 	 *
558 	 * @throws Exception
559 	 */
560 	@Test
561 	public void testPushDefaultUpstreamTriangular() throws Exception {
562 		try (Git git = new Git(db);
563 				Git git2 = new Git(createBareRepository())) {
564 			StoredConfig config = git.getRepository().getConfig();
565 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
566 			URIish uri = new URIish(
567 					git2.getRepository().getDirectory().toURI().toURL());
568 			remoteConfig.addURI(uri);
569 			remoteConfig.addFetchRefSpec(
570 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
571 			remoteConfig.update(config);
572 			config.save();
573 
574 			writeTrashFile("f", "content of f");
575 			git.add().addFilepattern("f").call();
576 			git.commit().setMessage("adding f").call();
577 
578 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
579 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
580 
581 			config = git.getRepository().getConfig();
582 			// Don't configure a remote; it'll default to "origin".
583 			config.setString("branch", "branchtopush", "merge",
584 					"upstreambranch");
585 			config.save();
586 
587 			assertThrows(InvalidRefNameException.class,
588 					() -> git.push().setRemote("test")
589 							.setPushDefault(PushDefault.UPSTREAM).call());
590 		}
591 	}
592 
593 	/**
594 	 * Check that push.default=simple without refspec pushes only the current
595 	 * branch to the configured upstream name.
596 	 *
597 	 * @throws Exception
598 	 */
599 	@Test
600 	public void testPushDefaultSimple() throws Exception {
601 		try (Git git = new Git(db);
602 				Git git2 = new Git(createBareRepository())) {
603 			StoredConfig config = git.getRepository().getConfig();
604 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
605 			URIish uri = new URIish(
606 					git2.getRepository().getDirectory().toURI().toURL());
607 			remoteConfig.addURI(uri);
608 			remoteConfig.addFetchRefSpec(
609 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
610 			remoteConfig.update(config);
611 			config.save();
612 
613 			writeTrashFile("f", "content of f");
614 			git.add().addFilepattern("f").call();
615 			RevCommit commit = git.commit().setMessage("adding f").call();
616 
617 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
618 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
619 
620 			config = git.getRepository().getConfig();
621 			config.setString("branch", "branchtopush", "remote", "test");
622 			config.setString("branch", "branchtopush", "merge",
623 					"refs/heads/branchtopush");
624 			config.save();
625 
626 			assertEquals(null,
627 					git2.getRepository().resolve("refs/heads/branchtopush"));
628 			assertEquals(null,
629 					git2.getRepository().resolve("refs/heads/not-pushed"));
630 			assertEquals(null,
631 					git2.getRepository().resolve("refs/heads/master"));
632 			git.push().setRemote("test").setPushDefault(PushDefault.SIMPLE)
633 					.call();
634 			assertEquals(commit.getId(),
635 					git2.getRepository().resolve("refs/heads/branchtopush"));
636 			assertEquals(null,
637 					git2.getRepository().resolve("refs/heads/not-pushed"));
638 			assertEquals(null,
639 					git2.getRepository().resolve("refs/heads/master"));
640 			assertEquals(commit.getId(), git.getRepository()
641 					.resolve("refs/remotes/origin/branchtopush"));
642 		}
643 	}
644 
645 	/**
646 	 * Check that push.default=simple without refspec pushes only the current
647 	 * branch to a branch with the same name in a triangular workflow.
648 	 *
649 	 * @throws Exception
650 	 */
651 	@Test
652 	public void testPushDefaultSimpleTriangular() throws Exception {
653 		try (Git git = new Git(db);
654 				Git git2 = new Git(createBareRepository())) {
655 			StoredConfig config = git.getRepository().getConfig();
656 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
657 			URIish uri = new URIish(
658 					git2.getRepository().getDirectory().toURI().toURL());
659 			remoteConfig.addURI(uri);
660 			remoteConfig.addFetchRefSpec(
661 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
662 			remoteConfig.update(config);
663 			config.save();
664 
665 			writeTrashFile("f", "content of f");
666 			git.add().addFilepattern("f").call();
667 			RevCommit commit = git.commit().setMessage("adding f").call();
668 
669 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
670 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
671 
672 			config = git.getRepository().getConfig();
673 			// Don't set remote, it'll default to "origin". Configure a
674 			// different branch name; should be ignored.
675 			config.setString("branch", "branchtopush", "merge",
676 					"refs/heads/upstreambranch");
677 			config.save();
678 
679 			assertEquals(null,
680 					git2.getRepository().resolve("refs/heads/branchtopush"));
681 			assertEquals(null,
682 					git2.getRepository().resolve("refs/heads/upstreambranch"));
683 			assertEquals(null,
684 					git2.getRepository().resolve("refs/heads/not-pushed"));
685 			assertEquals(null,
686 					git2.getRepository().resolve("refs/heads/master"));
687 			git.push().setRemote("test").setPushDefault(PushDefault.SIMPLE)
688 					.call();
689 			assertEquals(commit.getId(),
690 					git2.getRepository().resolve("refs/heads/branchtopush"));
691 			assertEquals(null,
692 					git2.getRepository().resolve("refs/heads/upstreambranch"));
693 			assertEquals(null,
694 					git2.getRepository().resolve("refs/heads/not-pushed"));
695 			assertEquals(null,
696 					git2.getRepository().resolve("refs/heads/master"));
697 			assertEquals(commit.getId(), git.getRepository()
698 					.resolve("refs/remotes/origin/branchtopush"));
699 		}
700 	}
701 
702 	/**
703 	 * Check that push.default=simple without refspec throws an
704 	 * InvalidRefNameException if the current branch has no upstream.
705 	 *
706 	 * @throws Exception
707 	 */
708 	@Test
709 	public void testPushDefaultSimpleNoTracking() throws Exception {
710 		try (Git git = new Git(db);
711 				Git git2 = new Git(createBareRepository())) {
712 			StoredConfig config = git.getRepository().getConfig();
713 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
714 			URIish uri = new URIish(
715 					git2.getRepository().getDirectory().toURI().toURL());
716 			remoteConfig.addURI(uri);
717 			remoteConfig.addFetchRefSpec(
718 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
719 			remoteConfig.update(config);
720 			config.save();
721 
722 			writeTrashFile("f", "content of f");
723 			git.add().addFilepattern("f").call();
724 			git.commit().setMessage("adding f").call();
725 
726 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
727 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
728 
729 			config = git.getRepository().getConfig();
730 			config.setString("branch", "branchtopush", "remote", "test");
731 			config.save();
732 
733 			assertThrows(InvalidRefNameException.class,
734 					() -> git.push().setRemote("test")
735 							.setPushDefault(PushDefault.SIMPLE).call());
736 		}
737 	}
738 
739 	/**
740 	 * Check that push.default=simple without refspec throws an
741 	 * InvalidRefNameException if the current branch has an upstream with a
742 	 * different name.
743 	 *
744 	 * @throws Exception
745 	 */
746 	@Test
747 	public void testPushDefaultSimpleDifferentTracking() throws Exception {
748 		try (Git git = new Git(db);
749 				Git git2 = new Git(createBareRepository())) {
750 			StoredConfig config = git.getRepository().getConfig();
751 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
752 			URIish uri = new URIish(
753 					git2.getRepository().getDirectory().toURI().toURL());
754 			remoteConfig.addURI(uri);
755 			remoteConfig.addFetchRefSpec(
756 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
757 			remoteConfig.update(config);
758 			config.save();
759 
760 			writeTrashFile("f", "content of f");
761 			git.add().addFilepattern("f").call();
762 			git.commit().setMessage("adding f").call();
763 
764 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
765 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
766 
767 			config = git.getRepository().getConfig();
768 			config.setString("branch", "branchtopush", "remote", "test");
769 			config.setString("branch", "branchtopush", "merge",
770 					"refs/heads/upstreambranch");
771 			config.save();
772 
773 			assertThrows(InvalidRefNameException.class,
774 					() -> git.push().setRemote("test")
775 							.setPushDefault(PushDefault.SIMPLE).call());
776 		}
777 	}
778 
779 	/**
780 	 * Check that if no PushDefault is set, the value is read from the git
781 	 * config.
782 	 *
783 	 * @throws Exception
784 	 */
785 	@Test
786 	public void testPushDefaultFromConfig() throws Exception {
787 		try (Git git = new Git(db);
788 				Git git2 = new Git(createBareRepository())) {
789 			StoredConfig config = git.getRepository().getConfig();
790 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
791 			URIish uri = new URIish(
792 					git2.getRepository().getDirectory().toURI().toURL());
793 			remoteConfig.addURI(uri);
794 			remoteConfig.addFetchRefSpec(
795 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
796 			remoteConfig.update(config);
797 			config.setString("push", null, "default", "upstream");
798 			config.save();
799 
800 			writeTrashFile("f", "content of f");
801 			git.add().addFilepattern("f").call();
802 			RevCommit commit = git.commit().setMessage("adding f").call();
803 
804 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
805 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
806 
807 			config = git.getRepository().getConfig();
808 			config.setString("branch", "branchtopush", "remote", "test");
809 			config.setString("branch", "branchtopush", "merge",
810 					"refs/heads/upstreambranch");
811 			config.save();
812 
813 			assertEquals(null,
814 					git2.getRepository().resolve("refs/heads/branchtopush"));
815 			assertEquals(null,
816 					git2.getRepository().resolve("refs/heads/upstreambranch"));
817 			assertEquals(null,
818 					git2.getRepository().resolve("refs/heads/not-pushed"));
819 			assertEquals(null,
820 					git2.getRepository().resolve("refs/heads/master"));
821 			PushCommand cmd = git.push();
822 			cmd.setRemote("test").setPushDefault(null).call();
823 			assertEquals(PushDefault.UPSTREAM, cmd.getPushDefault());
824 			assertEquals(null,
825 					git2.getRepository().resolve("refs/heads/branchtopush"));
826 			assertEquals(commit.getId(),
827 					git2.getRepository().resolve("refs/heads/upstreambranch"));
828 			assertEquals(null,
829 					git2.getRepository().resolve("refs/heads/not-pushed"));
830 			assertEquals(null,
831 					git2.getRepository().resolve("refs/heads/master"));
832 			assertEquals(commit.getId(), git.getRepository()
833 					.resolve("refs/remotes/origin/upstreambranch"));
834 			assertEquals(null, git.getRepository()
835 					.resolve("refs/remotes/origin/branchtopush"));
836 		}
837 	}
838 
839 	/**
840 	 * Check that if no PushDefault is set and none is set in the git config, it
841 	 * defaults to "simple".
842 	 *
843 	 * @throws Exception
844 	 */
845 	@Test
846 	public void testPushDefaultFromConfigDefault() throws Exception {
847 		try (Git git = new Git(db);
848 				Git git2 = new Git(createBareRepository())) {
849 			StoredConfig config = git.getRepository().getConfig();
850 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
851 			URIish uri = new URIish(
852 					git2.getRepository().getDirectory().toURI().toURL());
853 			remoteConfig.addURI(uri);
854 			remoteConfig.addFetchRefSpec(
855 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
856 			remoteConfig.update(config);
857 			config.save();
858 
859 			writeTrashFile("f", "content of f");
860 			git.add().addFilepattern("f").call();
861 			RevCommit commit = git.commit().setMessage("adding f").call();
862 
863 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
864 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
865 
866 			config = git.getRepository().getConfig();
867 			config.setString("branch", "branchtopush", "remote", "test");
868 			config.setString("branch", "branchtopush", "merge",
869 					"refs/heads/branchtopush");
870 			config.save();
871 
872 			assertEquals(null,
873 					git2.getRepository().resolve("refs/heads/branchtopush"));
874 			assertEquals(null,
875 					git2.getRepository().resolve("refs/heads/not-pushed"));
876 			assertEquals(null,
877 					git2.getRepository().resolve("refs/heads/master"));
878 			PushCommand cmd = git.push();
879 			cmd.setRemote("test").setPushDefault(null).call();
880 			assertEquals(PushDefault.SIMPLE, cmd.getPushDefault());
881 			assertEquals(commit.getId(),
882 					git2.getRepository().resolve("refs/heads/branchtopush"));
883 			assertEquals(null,
884 					git2.getRepository().resolve("refs/heads/not-pushed"));
885 			assertEquals(null,
886 					git2.getRepository().resolve("refs/heads/master"));
887 			assertEquals(commit.getId(), git.getRepository()
888 					.resolve("refs/remotes/origin/branchtopush"));
889 		}
890 	}
891 
892 	/**
893 	 * Check that branch.<name>.pushRemote overrides anything else.
894 	 *
895 	 * @throws Exception
896 	 */
897 	@Test
898 	public void testBranchPushRemote() throws Exception {
899 		try (Git git = new Git(db);
900 				Git git2 = new Git(createBareRepository())) {
901 			StoredConfig config = git.getRepository().getConfig();
902 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
903 			URIish uri = new URIish(
904 					git2.getRepository().getDirectory().toURI().toURL());
905 			remoteConfig.addURI(uri);
906 			remoteConfig.addFetchRefSpec(
907 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
908 			remoteConfig.update(config);
909 			config.setString("remote", null, "pushDefault", "test");
910 			config.save();
911 
912 			writeTrashFile("f", "content of f");
913 			git.add().addFilepattern("f").call();
914 			git.commit().setMessage("adding f").call();
915 
916 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
917 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
918 
919 			config = git.getRepository().getConfig();
920 			config.setString("branch", "branchtopush", "remote", "test");
921 			config.setString("branch", "branchtopush", "pushremote", "origin");
922 			config.setString("branch", "branchtopush", "merge",
923 					"refs/heads/branchtopush");
924 			config.save();
925 
926 			assertThrows(InvalidRefNameException.class, () -> git.push()
927 					.setPushDefault(PushDefault.UPSTREAM).call());
928 		}
929 	}
930 
931 	/**
932 	 * Check that remote.pushDefault overrides branch.<name>.remote
933 	 *
934 	 * @throws Exception
935 	 */
936 	@Test
937 	public void testRemotePushDefault() throws Exception {
938 		try (Git git = new Git(db);
939 				Git git2 = new Git(createBareRepository())) {
940 			StoredConfig config = git.getRepository().getConfig();
941 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
942 			URIish uri = new URIish(
943 					git2.getRepository().getDirectory().toURI().toURL());
944 			remoteConfig.addURI(uri);
945 			remoteConfig.addFetchRefSpec(
946 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
947 			remoteConfig.update(config);
948 			config.setString("remote", null, "pushDefault", "origin");
949 			config.save();
950 
951 			writeTrashFile("f", "content of f");
952 			git.add().addFilepattern("f").call();
953 			git.commit().setMessage("adding f").call();
954 
955 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
956 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
957 
958 			config = git.getRepository().getConfig();
959 			config.setString("branch", "branchtopush", "remote", "test");
960 			config.setString("branch", "branchtopush", "merge",
961 					"refs/heads/branchtopush");
962 			config.save();
963 
964 			assertThrows(InvalidRefNameException.class, () -> git.push()
965 					.setPushDefault(PushDefault.UPSTREAM).call());
966 		}
967 	}
968 
969 	/**
970 	 * Check that ultimately we fall back to "origin".
971 	 *
972 	 * @throws Exception
973 	 */
974 	@Test
975 	public void testDefaultRemote() throws Exception {
976 		try (Git git = new Git(db);
977 				Git git2 = new Git(createBareRepository())) {
978 			StoredConfig config = git.getRepository().getConfig();
979 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
980 			URIish uri = new URIish(
981 					git2.getRepository().getDirectory().toURI().toURL());
982 			remoteConfig.addURI(uri);
983 			remoteConfig.addFetchRefSpec(
984 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
985 			remoteConfig.update(config);
986 			config.save();
987 
988 			writeTrashFile("f", "content of f");
989 			git.add().addFilepattern("f").call();
990 			git.commit().setMessage("adding f").call();
991 
992 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
993 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
994 
995 			config = git.getRepository().getConfig();
996 			config.setString("branch", "branchtopush", "merge",
997 					"refs/heads/branchtopush");
998 			config.save();
999 
1000 			PushCommand cmd = git.push().setPushDefault(PushDefault.UPSTREAM);
1001 			TransportException e = assertThrows(TransportException.class,
1002 					() -> cmd.call());
1003 			assertEquals(NoRemoteRepositoryException.class,
1004 					e.getCause().getClass());
1005 			assertEquals("origin", cmd.getRemote());
1006 		}
1007 	}
1008 
1009 	/**
1010 	 * Check that a push without specifying a remote or mode or anything can
1011 	 * succeed if the git config is correct.
1012 	 *
1013 	 * @throws Exception
1014 	 */
1015 	@Test
1016 	public void testDefaultPush() throws Exception {
1017 		try (Git git = new Git(db);
1018 				Git git2 = new Git(createBareRepository())) {
1019 			StoredConfig config = git.getRepository().getConfig();
1020 			RemoteConfig remoteConfig = new RemoteConfig(config, "test");
1021 			URIish uri = new URIish(
1022 					git2.getRepository().getDirectory().toURI().toURL());
1023 			remoteConfig.addURI(uri);
1024 			remoteConfig.addFetchRefSpec(
1025 					new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
1026 			remoteConfig.update(config);
1027 			config.save();
1028 
1029 			writeTrashFile("f", "content of f");
1030 			git.add().addFilepattern("f").call();
1031 			RevCommit commit = git.commit().setMessage("adding f").call();
1032 
1033 			git.checkout().setName("not-pushed").setCreateBranch(true).call();
1034 			git.checkout().setName("branchtopush").setCreateBranch(true).call();
1035 
1036 			config = git.getRepository().getConfig();
1037 			config.setString("branch", "branchtopush", "remote", "test");
1038 			config.save();
1039 
1040 			assertEquals(null,
1041 					git2.getRepository().resolve("refs/heads/branchtopush"));
1042 			assertEquals(null,
1043 					git2.getRepository().resolve("refs/heads/not-pushed"));
1044 			assertEquals(null,
1045 					git2.getRepository().resolve("refs/heads/master"));
1046 			// Should use remote "test", push.default=current
1047 			PushCommand cmd = git.push();
1048 			cmd.call();
1049 			assertEquals("test", cmd.getRemote());
1050 			assertEquals(PushDefault.CURRENT, cmd.getPushDefault());
1051 			assertEquals(commit.getId(),
1052 					git2.getRepository().resolve("refs/heads/branchtopush"));
1053 			assertEquals(null,
1054 					git2.getRepository().resolve("refs/heads/not-pushed"));
1055 			assertEquals(null,
1056 					git2.getRepository().resolve("refs/heads/master"));
1057 			assertEquals(commit.getId(), git.getRepository()
1058 					.resolve("refs/remotes/origin/branchtopush"));
1059 		}
1060 	}
1061 
1062 	/**
1063 	 * Check that missing refs don't cause errors during push
1064 	 *
1065 	 * @throws Exception
1066 	 */
1067 	@Test
1068 	public void testPushAfterGC() throws Exception {
1069 		// create other repository
1070 		Repository db2 = createWorkRepository();
1071 		addRepoToClose(db2);
1072 
1073 		// setup the first repository
1074 		final StoredConfig config = db.getConfig();
1075 		RemoteConfig remoteConfig = new RemoteConfig(config, "test");
1076 		URIish uri = new URIish(db2.getDirectory().toURI().toURL());
1077 		remoteConfig.addURI(uri);
1078 		remoteConfig.update(config);
1079 		config.save();
1080 
1081 		try (Git git1 = new Git(db);
1082 				Git git2 = new Git(db2)) {
1083 			// push master (with a new commit) to the remote
1084 			git1.commit().setMessage("initial commit").call();
1085 
1086 			RefSpec spec = new RefSpec("refs/heads/*:refs/heads/*");
1087 			git1.push().setRemote("test").setRefSpecs(spec).call();
1088 
1089 			// create an unrelated ref and a commit on our remote
1090 			git2.branchCreate().setName("refs/heads/other").call();
1091 			git2.checkout().setName("refs/heads/other").call();
1092 
1093 			writeTrashFile("a", "content of a");
1094 			git2.add().addFilepattern("a").call();
1095 			RevCommit commit2 = git2.commit().setMessage("adding a").call();
1096 
1097 			// run a gc to ensure we have a bitmap index
1098 			Properties res = git1.gc().setExpire(null).call();
1099 			assertEquals(8, res.size());
1100 
1101 			// create another commit so we have something else to push
1102 			writeTrashFile("b", "content of b");
1103 			git1.add().addFilepattern("b").call();
1104 			RevCommit commit3 = git1.commit().setMessage("adding b").call();
1105 
1106 			try {
1107 				// Re-run the push.  Failure may happen here.
1108 				git1.push().setRemote("test").setRefSpecs(spec).call();
1109 			} catch (TransportException e) {
1110 				assertTrue("should be caused by a MissingObjectException", e
1111 						.getCause().getCause() instanceof MissingObjectException);
1112 				fail("caught MissingObjectException for a change we don't have");
1113 			}
1114 
1115 			// Remote will have both a and b.  Master will have only b
1116 			try {
1117 				db.resolve(commit2.getId().getName() + "^{commit}");
1118 				fail("id shouldn't exist locally");
1119 			} catch (MissingObjectException e) {
1120 				// we should get here
1121 			}
1122 			assertEquals(commit2.getId(),
1123 					db2.resolve(commit2.getId().getName() + "^{commit}"));
1124 			assertEquals(commit3.getId(),
1125 					db2.resolve(commit3.getId().getName() + "^{commit}"));
1126 		}
1127 	}
1128 
1129 	@Test
1130 	public void testPushWithLease() throws JGitInternalException, IOException,
1131 			GitAPIException, URISyntaxException {
1132 
1133 		// create other repository
1134 		Repository db2 = createWorkRepository();
1135 		addRepoToClose(db2);
1136 
1137 		// setup the first repository
1138 		final StoredConfig config = db.getConfig();
1139 		RemoteConfig remoteConfig = new RemoteConfig(config, "test");
1140 		URIish uri = new URIish(db2.getDirectory().toURI().toURL());
1141 		remoteConfig.addURI(uri);
1142 		remoteConfig.update(config);
1143 		config.save();
1144 
1145 		try (Git git1 = new Git(db)) {
1146 			// create one commit and push it
1147 			RevCommit commit = git1.commit().setMessage("initial commit").call();
1148 			git1.branchCreate().setName("initial").call();
1149 
1150 			RefSpec spec = new RefSpec("refs/heads/master:refs/heads/x");
1151 			git1.push().setRemote("test").setRefSpecs(spec)
1152 					.call();
1153 
1154 			assertEquals(commit.getId(),
1155 					db2.resolve(commit.getId().getName() + "^{commit}"));
1156 			//now try to force-push a new commit, with a good lease
1157 
1158 			git1.commit().setMessage("second commit").call();
1159 			Iterable<PushResult> results =
1160 					git1.push().setRemote("test").setRefSpecs(spec)
1161 							.setRefLeaseSpecs(new RefLeaseSpec("refs/heads/x", "initial"))
1162 							.call();
1163 			for (PushResult result : results) {
1164 				RemoteRefUpdate update = result.getRemoteUpdate("refs/heads/x");
1165 				assertEquals(update.getStatus(), RemoteRefUpdate.Status.OK);
1166 			}
1167 
1168 			git1.commit().setMessage("third commit").call();
1169 			//now try to force-push a new commit, with a bad lease
1170 
1171 			results =
1172 					git1.push().setRemote("test").setRefSpecs(spec)
1173 							.setRefLeaseSpecs(new RefLeaseSpec("refs/heads/x", "initial"))
1174 							.call();
1175 			for (PushResult result : results) {
1176 				RemoteRefUpdate update = result.getRemoteUpdate("refs/heads/x");
1177 				assertEquals(update.getStatus(), RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED);
1178 			}
1179 		}
1180 	}
1181 }