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.assertFalse;
47 import static org.junit.Assert.assertNotNull;
48 import static org.junit.Assert.assertNull;
49 import static org.junit.Assert.assertTrue;
50
51 import java.io.ByteArrayOutputStream;
52 import java.io.File;
53 import java.io.FileInputStream;
54 import java.io.FileOutputStream;
55 import java.io.IOException;
56
57 import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
58 import org.eclipse.jgit.api.MergeResult.MergeStatus;
59 import org.eclipse.jgit.api.RebaseResult.Status;
60 import org.eclipse.jgit.junit.RepositoryTestCase;
61 import org.eclipse.jgit.lib.ConfigConstants;
62 import org.eclipse.jgit.lib.Constants;
63 import org.eclipse.jgit.lib.ObjectId;
64 import org.eclipse.jgit.lib.Ref;
65 import org.eclipse.jgit.lib.Repository;
66 import org.eclipse.jgit.lib.RepositoryState;
67 import org.eclipse.jgit.lib.StoredConfig;
68 import org.eclipse.jgit.merge.MergeStrategy;
69 import org.eclipse.jgit.revwalk.RevCommit;
70 import org.eclipse.jgit.revwalk.RevWalk;
71 import org.eclipse.jgit.transport.RefSpec;
72 import org.eclipse.jgit.transport.RemoteConfig;
73 import org.eclipse.jgit.transport.URIish;
74 import org.junit.Before;
75 import org.junit.Test;
76
77 public class PullCommandWithRebaseTest extends RepositoryTestCase {
78
79 protected Repository dbTarget;
80
81 private Git source;
82
83 private Git target;
84
85 private File sourceFile;
86
87 private File targetFile;
88
89 @Test
90 public void testPullFastForward() throws Exception {
91 PullResult res = target.pull().call();
92
93 assertTrue(res.getFetchResult().getTrackingRefUpdates().isEmpty());
94 assertEquals(Status.UP_TO_DATE, res.getRebaseResult().getStatus());
95
96 assertFileContentsEqual(targetFile, "Hello world");
97
98
99 writeToFile(sourceFile, "Another change");
100 source.add().addFilepattern("SomeFile.txt").call();
101 source.commit().setMessage("Some change in remote").call();
102
103 res = target.pull().call();
104
105 assertFalse(res.getFetchResult().getTrackingRefUpdates().isEmpty());
106 assertEquals(Status.FAST_FORWARD, res.getRebaseResult().getStatus());
107 assertFileContentsEqual(targetFile, "Another change");
108 assertEquals(RepositoryState.SAFE, target.getRepository()
109 .getRepositoryState());
110
111 res = target.pull().call();
112 assertEquals(Status.UP_TO_DATE, res.getRebaseResult().getStatus());
113 }
114
115 @Test
116 public void testPullFastForwardWithBranchInSource() throws Exception {
117 PullResult res = target.pull().call();
118
119 assertTrue(res.getFetchResult().getTrackingRefUpdates().isEmpty());
120 assertEquals(Status.UP_TO_DATE, res.getRebaseResult().getStatus());
121
122 assertFileContentsEqual(targetFile, "Hello world");
123
124
125 writeToFile(sourceFile, "Another change\n\n\n\nFoo");
126 source.add().addFilepattern("SomeFile.txt").call();
127 RevCommit initialCommit = source.commit()
128 .setMessage("Some change in remote").call();
129
130
131 createBranch(initialCommit, "refs/heads/side");
132 checkoutBranch("refs/heads/side");
133 writeToFile(sourceFile, "Another change\n\n\n\nBoo");
134 source.add().addFilepattern("SomeFile.txt").call();
135 RevCommit sideCommit = source.commit()
136 .setMessage("Some change in remote").call();
137
138
139 checkoutBranch("refs/heads/master");
140 writeToFile(sourceFile, "More change\n\n\n\nFoo");
141 source.add().addFilepattern("SomeFile.txt").call();
142 source.commit().setMessage("Some change in remote").call();
143
144
145 MergeResult result = source.merge().include(sideCommit.getId())
146 .setStrategy(MergeStrategy.RESOLVE).call();
147 assertEquals(MergeStatus.MERGED, result.getMergeStatus());
148
149 }
150
151 @Test
152 public void testPullFastForwardDetachedHead() throws Exception {
153 Repository repository = source.getRepository();
154 writeToFile(sourceFile, "2nd commit");
155 source.add().addFilepattern("SomeFile.txt").call();
156 source.commit().setMessage("2nd commit").call();
157
158 try (RevWalk revWalk = new RevWalk(repository)) {
159
160 String initialBranch = repository.getBranch();
161 Ref initialRef = repository.findRef(Constants.HEAD);
162 RevCommit initialCommit = revWalk
163 .parseCommit(initialRef.getObjectId());
164 assertEquals("this test need linear history", 1,
165 initialCommit.getParentCount());
166 source.checkout().setName(initialCommit.getParent(0).getName())
167 .call();
168 assertFalse("expected detached HEAD",
169 repository.getFullBranch().startsWith(Constants.R_HEADS));
170
171
172 File otherFile = new File(sourceFile.getParentFile(),
173 System.currentTimeMillis() + ".tst");
174 writeToFile(otherFile, "other 2nd commit");
175 source.add().addFilepattern(otherFile.getName()).call();
176 RevCommit newCommit = source.commit().setMessage("other 2nd commit")
177 .call();
178
179
180 source.pull().setRebase(true).setRemote(".")
181 .setRemoteBranchName(initialBranch)
182 .call();
183
184 assertEquals(RepositoryState.SAFE,
185 source.getRepository().getRepositoryState());
186 Ref head = source.getRepository().findRef(Constants.HEAD);
187 RevCommit headCommit = revWalk.parseCommit(head.getObjectId());
188
189
190 assertEquals(1, headCommit.getParentCount());
191 assertEquals(initialCommit, headCommit.getParent(0));
192
193
194 assertFileContentsEqual(sourceFile, "2nd commit");
195 assertFileContentsEqual(otherFile, "other 2nd commit");
196
197 assertEquals(newCommit.getShortMessage(),
198 headCommit.getShortMessage());
199 }
200 }
201
202 @Test
203 public void testPullConflict() throws Exception {
204 PullResult res = target.pull().call();
205
206 assertTrue(res.getFetchResult().getTrackingRefUpdates().isEmpty());
207 assertEquals(Status.UP_TO_DATE, res.getRebaseResult().getStatus());
208
209 assertFileContentsEqual(targetFile, "Hello world");
210
211
212 writeToFile(sourceFile, "Source change");
213 source.add().addFilepattern("SomeFile.txt").call();
214 source.commit().setMessage("Source change in remote").call();
215
216
217 writeToFile(targetFile, "Target change");
218 target.add().addFilepattern("SomeFile.txt").call();
219 target.commit().setMessage("Target change in local").call();
220
221 res = target.pull().call();
222
223 String remoteUri = target
224 .getRepository()
225 .getConfig()
226 .getString(ConfigConstants.CONFIG_REMOTE_SECTION, "origin",
227 ConfigConstants.CONFIG_KEY_URL);
228
229 assertFalse(res.getFetchResult().getTrackingRefUpdates().isEmpty());
230 assertEquals(Status.STOPPED, res.getRebaseResult().getStatus());
231 String result = "<<<<<<< Upstream, based on branch 'master' of "
232 + remoteUri
233 + "\nSource change\n=======\nTarget change\n>>>>>>> 42453fd Target change in local\n";
234 assertFileContentsEqual(targetFile, result);
235 assertEquals(RepositoryState.REBASING_MERGE, target
236 .getRepository().getRepositoryState());
237 }
238
239 @Test
240 public void testPullLocalConflict() throws Exception {
241 target.branchCreate().setName("basedOnMaster").setStartPoint(
242 "refs/heads/master").setUpstreamMode(SetupUpstreamMode.NOTRACK)
243 .call();
244 StoredConfig config = target.getRepository().getConfig();
245 config.setString("branch", "basedOnMaster", "remote", ".");
246 config.setString("branch", "basedOnMaster", "merge",
247 "refs/heads/master");
248 config.setBoolean("branch", "basedOnMaster", "rebase", true);
249 config.save();
250 target.getRepository().updateRef(Constants.HEAD).link(
251 "refs/heads/basedOnMaster");
252 PullResult res = target.pull().call();
253
254 assertNull(res.getFetchResult());
255 assertEquals(Status.UP_TO_DATE, res.getRebaseResult().getStatus());
256
257 assertFileContentsEqual(targetFile, "Hello world");
258
259
260 target.getRepository().updateRef(Constants.HEAD).link(
261 "refs/heads/master");
262 writeToFile(targetFile, "Master change");
263 target.add().addFilepattern("SomeFile.txt").call();
264 target.commit().setMessage("Source change in master").call();
265
266
267 target.getRepository().updateRef(Constants.HEAD).link(
268 "refs/heads/basedOnMaster");
269 writeToFile(targetFile, "Slave change");
270 target.add().addFilepattern("SomeFile.txt").call();
271 target.commit().setMessage("Source change in based on master").call();
272
273 res = target.pull().call();
274
275 assertNull(res.getFetchResult());
276 assertEquals(Status.STOPPED, res.getRebaseResult().getStatus());
277 String result = "<<<<<<< Upstream, based on branch 'master' of local repository\n"
278 + "Master change\n=======\nSlave change\n>>>>>>> 4049c9e Source change in based on master\n";
279 assertFileContentsEqual(targetFile, result);
280 assertEquals(RepositoryState.REBASING_MERGE, target
281 .getRepository().getRepositoryState());
282 }
283
284 @Test
285 public void testPullFastForwardWithLocalCommitAndRebaseFlagSet() throws Exception {
286 final String SOURCE_COMMIT_MESSAGE = "Source commit message for rebase flag test";
287 final String TARGET_COMMIT_MESSAGE = "Target commit message for rebase flag test";
288
289 assertFalse(SOURCE_COMMIT_MESSAGE.equals(TARGET_COMMIT_MESSAGE));
290
291 final String SOURCE_FILE_CONTENTS = "Source change";
292 final String NEW_FILE_CONTENTS = "New file from target";
293
294
295
296 StoredConfig targetConfig = dbTarget.getConfig();
297 targetConfig.setBoolean("branch", "master", "rebase", false);
298 targetConfig.save();
299
300
301 writeToFile(sourceFile, SOURCE_FILE_CONTENTS);
302 source.add().addFilepattern(sourceFile.getName()).call();
303 source.commit().setMessage(SOURCE_COMMIT_MESSAGE).call();
304
305
306 File newFile = new File(dbTarget.getWorkTree().getPath() + "/newFile.txt");
307 writeToFile(newFile, NEW_FILE_CONTENTS);
308 target.add().addFilepattern(newFile.getName()).call();
309 target.commit().setMessage(TARGET_COMMIT_MESSAGE).call();
310
311
312 assertFalse(targetConfig.getBoolean("branch", "master", "rebase", true));
313
314
315 PullResult pullResult = target.pull().setRebase(true).call();
316
317
318 assertTrue(pullResult.isSuccessful());
319
320
321 RebaseResult rebaseResult = pullResult.getRebaseResult();
322 assertNotNull(rebaseResult);
323 assertNull(rebaseResult.getFailingPaths());
324 assertEquals(Status.OK, rebaseResult.getStatus());
325
326
327 Repository targetRepo = target.getRepository();
328 try (RevWalk revWalk = new RevWalk(targetRepo)) {
329 ObjectId headId = targetRepo.resolve(Constants.HEAD);
330 RevCommit root = revWalk.parseCommit(headId);
331 revWalk.markStart(root);
332
333 RevCommit head = revWalk.next();
334
335 RevCommit beforeHead = revWalk.next();
336
337
338 assertEquals(TARGET_COMMIT_MESSAGE, head.getFullMessage());
339
340 assertEquals(SOURCE_COMMIT_MESSAGE, beforeHead.getFullMessage());
341
342
343 assertFileContentsEqual(sourceFile, SOURCE_FILE_CONTENTS);
344 assertFileContentsEqual(newFile, NEW_FILE_CONTENTS);
345
346 assertEquals(RepositoryState.SAFE, target
347 .getRepository().getRepositoryState());
348 }
349 }
350
351 @Override
352 @Before
353 public void setUp() throws Exception {
354 super.setUp();
355 dbTarget = createWorkRepository();
356 source = new Git(db);
357 target = new Git(dbTarget);
358
359
360 sourceFile = new File(db.getWorkTree(), "SomeFile.txt");
361 writeToFile(sourceFile, "Hello world");
362
363 source.add().addFilepattern("SomeFile.txt").call();
364 source.commit().setMessage("Initial commit for source").call();
365
366
367 StoredConfig targetConfig = dbTarget.getConfig();
368 targetConfig.setString("branch", "master", "remote", "origin");
369 targetConfig
370 .setString("branch", "master", "merge", "refs/heads/master");
371 RemoteConfig config = new RemoteConfig(targetConfig, "origin");
372
373 config
374 .addURI(new URIish(source.getRepository().getWorkTree()
375 .getAbsolutePath()));
376 config.addFetchRefSpec(new RefSpec(
377 "+refs/heads/*:refs/remotes/origin/*"));
378 config.update(targetConfig);
379 targetConfig.save();
380
381 targetFile = new File(dbTarget.getWorkTree(), "SomeFile.txt");
382
383 target.pull().call();
384 target.checkout().setStartPoint("refs/remotes/origin/master").setName(
385 "master").call();
386
387 targetConfig
388 .setString("branch", "master", "merge", "refs/heads/master");
389 targetConfig.setBoolean("branch", "master", "rebase", true);
390 targetConfig.save();
391
392 assertFileContentsEqual(targetFile, "Hello world");
393 }
394
395 private static void writeToFile(File actFile, String string)
396 throws IOException {
397 FileOutputStream fos = null;
398 try {
399 fos = new FileOutputStream(actFile);
400 fos.write(string.getBytes("UTF-8"));
401 fos.close();
402 } finally {
403 if (fos != null)
404 fos.close();
405 }
406 }
407
408 private static void assertFileContentsEqual(File actFile, String string)
409 throws IOException {
410 ByteArrayOutputStream bos = new ByteArrayOutputStream();
411 FileInputStream fis = null;
412 byte[] buffer = new byte[100];
413 try {
414 fis = new FileInputStream(actFile);
415 int read = fis.read(buffer);
416 while (read > 0) {
417 bos.write(buffer, 0, read);
418 read = fis.read(buffer);
419 }
420 String content = new String(bos.toByteArray(), "UTF-8");
421 assertEquals(string, content);
422 } finally {
423 if (fis != null)
424 fis.close();
425 }
426 }
427 }