View Javadoc

1   /*
2    * #%L
3    * JavaHg
4    * %%
5    * Copyright (C) 2011 aragost Trifork ag
6    * %%
7    * Permission is hereby granted, free of charge, to any person obtaining a copy
8    * of this software and associated documentation files (the "Software"), to deal
9    * in the Software without restriction, including without limitation the rights
10   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11   * copies of the Software, and to permit persons to whom the Software is
12   * furnished to do so, subject to the following conditions:
13   * 
14   * The above copyright notice and this permission notice shall be included in
15   * all copies or substantial portions of the Software.
16   * 
17   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23   * THE SOFTWARE.
24   * #L%
25   */
26  package com.aragost.javahg.commands;
27  
28  import java.io.File;
29  import java.io.IOException;
30  import java.util.List;
31  
32  import org.junit.Assert;
33  import org.junit.Assume;
34  import org.junit.Test;
35  
36  import com.aragost.javahg.Changeset;
37  import com.aragost.javahg.Repository;
38  import com.aragost.javahg.internals.Utils;
39  import com.aragost.javahg.merge.ConflictResolvingContext;
40  import com.aragost.javahg.merge.KeepDeleteConflict;
41  import com.aragost.javahg.merge.MergeConflict;
42  import com.aragost.javahg.test.AbstractTestCase;
43  
44  public class MergeCommandTest extends AbstractTestCase {
45  
46      @Test
47      public void testManifestConflict() throws IOException {
48          Repository repo = getTestRepository();
49          CommitCommand commitCmd = CommitCommand.on(repo).message("m").user("user");
50          writeFile("a", "boo");
51          writeFile("b", "boo");
52          AddCommand.on(repo).execute();
53          Changeset baseCs = commitCmd.execute();
54  
55          writeFile("a", "bar");
56          writeFile("b", "bar");
57          AddCommand.on(repo).execute();
58          commitCmd.execute();
59  
60          update(baseCs);
61  
62          RemoveCommand.on(repo).execute("a", "b");
63          commitCmd.execute();
64  
65          MergeCommand mergeCmd = MergeCommand.on(repo);
66          ManifestMergeOracle oracle = new ManifestMergeOracle();
67          oracle.delete("a");
68          mergeCmd.execute(oracle);
69  
70          Assert.assertEquals(1, oracle.getMissingAnswers().size());
71          Assert.assertTrue(oracle.getMissingAnswers().contains("b"));
72          Assert.assertTrue(new File(repo.getDirectory(), "b").exists());
73          Assert.assertFalse(new File(repo.getDirectory(), "a").exists());
74      }
75  
76      @Test
77      public void testMergeConlict() throws IOException {
78          Repository repo = getTestRepository();
79          CommitCommand commitCmd = CommitCommand.on(repo).message("m").user("user");
80  
81          writeFile("a", "boo");
82          writeFile("b", "boo");
83          AddCommand.on(repo).execute();
84          Changeset baseCs = commitCmd.execute();
85  
86          writeFile("a", "bar");
87          writeFile("b", "bar");
88          commitCmd.execute();
89  
90          update(baseCs);
91  
92          writeFile("a", "foo");
93          writeFile("b", "foo");
94          commitCmd.execute();
95  
96          MergeCommand mergeCmd = MergeCommand.on(repo);
97          ManifestMergeOracle oracle = new ManifestMergeOracle();
98          boolean flag = mergeCmd.execute(oracle);
99          Assert.assertFalse(flag);
100         Assert.assertTrue(oracle.getMissingAnswers().isEmpty());
101 
102         commitCmd = CommitCommand.on(repo).user("user").message("m");
103         try {
104             commitCmd.execute();
105             assertFailedExecution(commitCmd);
106         } catch (ExecutionException e) {
107             // expected unresolved conflicts
108         }
109     }
110 
111     @Test
112     public void testMergeCtxAncestor() throws IOException {
113         Repository repo = getTestRepository();
114         Changeset base = createChangeset();
115         Changeset parent2 = createChangeset();
116         update(base);
117         Changeset parent1 = createChangeset();
118         ConflictResolvingContext ms = repo.workingCopy().merge(parent2);
119         Assert.assertEquals(parent1, ms.getLocal());
120         Assert.assertEquals(parent2, ms.getRemote());
121         Assert.assertEquals(base, ms.getBase());
122     }
123 
124     @Test
125     public void testMergeCtxKeepDeleteConflict() throws IOException {
126         Repository repo = getTestRepository();
127         writeFile("a", "");
128         Changeset base = commit();
129         writeFile("a", "a");
130         Changeset p2 = commit();
131         update(base);
132         repo.workingCopy().remove("a");
133         Changeset p1 = commit();
134 
135         ConflictResolvingContext ms = repo.workingCopy().merge(p2);
136         Assert.assertEquals(1, ms.getKeepDeleteConflicts().size());
137         KeepDeleteConflict keepDeleteConflict = ms.getKeepDeleteConflicts().iterator().next();
138         Assert.assertEquals(KeepDeleteConflict.State.KEEP, keepDeleteConflict.getState());
139         Assert.assertEquals("a", keepDeleteConflict.getFilename());
140         Assert.assertEquals(p2, keepDeleteConflict.getKeepParent());
141 
142         update(p2);
143         ms = repo.workingCopy().merge(p1);
144         Assert.assertEquals(1, ms.getKeepDeleteConflicts().size());
145         keepDeleteConflict = ms.getKeepDeleteConflicts().iterator().next();
146         Assert.assertEquals(KeepDeleteConflict.State.KEEP, keepDeleteConflict.getState());
147         Assert.assertEquals("a", keepDeleteConflict.getFilename());
148         Assert.assertEquals(p2, keepDeleteConflict.getKeepParent());
149 
150         File a = getTestRepository().file("a");
151         Assert.assertTrue(a.exists());
152         keepDeleteConflict.delete();
153         Assert.assertFalse(a.exists());
154         StatusResult status1 = repo.workingCopy().status();
155         Assert.assertArrayEquals(new String[] { "a" }, status1.getRemoved().toArray());
156         StatusResult status2 = repo.workingCopy().parent2Status();
157         Assert.assertTrue(status2.getRemoved().isEmpty());
158 
159         keepDeleteConflict.keep();
160         Assert.assertTrue(a.exists());
161         status1 = repo.workingCopy().status();
162         Assert.assertTrue(status1.getRemoved().isEmpty());
163         status2 = repo.workingCopy().parent2Status();
164         Assert.assertTrue(status2.getRemoved().isEmpty());
165     }
166 
167     @Test
168     public void testMergeCtxFlagConflict() throws IOException, InterruptedException {
169         // Windows does not (in the Mercurial world) support symlinks
170         Assume.assumeTrue(!Utils.isWindows());
171 
172         Repository repo = getTestRepository();
173         writeFile("x", "");
174         Changeset base = commit();
175         writeFile("a", "");
176         setExecutable(repo.file("a"));
177         Changeset parent2 = commit();
178         update(base);
179         createSymlink(repo.file("b"), repo.file("a"));
180         commit();
181 
182         ConflictResolvingContext mergeCtx = repo.workingCopy().merge(parent2);
183         Assert.assertEquals(1, mergeCtx.getFlagConflicts().size());
184         Assert.assertEquals("a", mergeCtx.getFlagConflicts().iterator().next().getFilename());
185     }
186 
187     private void createSymlink(File oldName, File newName) throws IOException, InterruptedException {
188         String[] cmd = new String[] { "ln", "-s", oldName.getAbsolutePath(), newName.getAbsolutePath() };
189         exec(cmd);
190     }
191 
192     private void setExecutable(File file) throws InterruptedException, IOException {
193         String[] cmd = new String[] { "chmod", "+x", file.getAbsolutePath() };
194         exec(cmd);
195     }
196 
197     private void exec(String[] cmd) throws InterruptedException, IOException {
198         Process process = Runtime.getRuntime().exec(cmd);
199         process.waitFor();
200         process.destroy();
201     }
202 
203     @Test
204     public void testMergeConflict() throws IOException {
205         Repository repo = getTestRepository();
206         // Merge conflict in a can not be resolved with internal:merge
207         // in b the conflict can
208         writeFile("a");
209         writeFile("b", "a\na\na\na\na\n");
210         Changeset base = commit();
211         writeFile("a", "XX");
212         writeFile("b", "X\na\na\na\na\n");
213         Changeset parent2 = commit();
214         update(base);
215         writeFile("a", "YY");
216         writeFile("b", "a\na\na\nY\na\n");
217         commit();
218 
219         ConflictResolvingContext mergeState = repo.workingCopy().merge(parent2);
220         List<MergeConflict> mergeConflicts = mergeState.getMergeConflicts();
221         Assert.assertEquals(2, mergeConflicts.size());
222         MergeConflict mca = mergeConflicts.get(0);
223         MergeConflict mcb = mergeConflicts.get(1);
224         Assert.assertEquals("a", mca.getFilename());
225         Assert.assertEquals("b", mcb.getFilename());
226 
227         Assert.assertFalse(mca.isResolved());
228         Assert.assertFalse(mcb.isResolved());
229 
230         mca.resolveWithInternalMerge();
231         mcb.resolveWithInternalMerge();
232 
233         Assert.assertFalse(mca.isResolved());
234         Assert.assertTrue(mcb.isResolved());
235 
236     }
237 }