1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.shared.release.phase;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.nio.file.LinkOption;
24 import java.util.Collections;
25 import java.util.List;
26
27 import org.apache.maven.project.MavenProject;
28 import org.apache.maven.scm.ScmBranchParameters;
29 import org.apache.maven.scm.ScmException;
30 import org.apache.maven.scm.ScmFile;
31 import org.apache.maven.scm.ScmFileSet;
32 import org.apache.maven.scm.ScmFileStatus;
33 import org.apache.maven.scm.command.branch.BranchScmResult;
34 import org.apache.maven.scm.manager.NoSuchScmProviderException;
35 import org.apache.maven.scm.manager.ScmManager;
36 import org.apache.maven.scm.provider.ScmProvider;
37 import org.apache.maven.scm.provider.ScmProviderStub;
38 import org.apache.maven.scm.provider.svn.repository.SvnScmProviderRepository;
39 import org.apache.maven.scm.repository.ScmRepository;
40 import org.apache.maven.scm.repository.ScmRepositoryException;
41 import org.apache.maven.shared.release.ReleaseExecutionException;
42 import org.apache.maven.shared.release.ReleaseFailureException;
43 import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder;
44 import org.apache.maven.shared.release.config.ReleaseUtils;
45 import org.apache.maven.shared.release.env.DefaultReleaseEnvironment;
46 import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
47 import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
48 import org.apache.maven.shared.release.stubs.ScmManagerStub;
49 import org.apache.maven.shared.release.util.ReleaseUtil;
50 import org.junit.Test;
51
52 import static org.junit.Assert.assertEquals;
53 import static org.junit.Assert.assertNull;
54 import static org.junit.Assert.assertTrue;
55 import static org.junit.Assert.fail;
56 import static org.mockito.ArgumentMatchers.argThat;
57 import static org.mockito.ArgumentMatchers.eq;
58 import static org.mockito.ArgumentMatchers.isA;
59 import static org.mockito.Mockito.mock;
60 import static org.mockito.Mockito.verify;
61 import static org.mockito.Mockito.verifyNoMoreInteractions;
62 import static org.mockito.Mockito.when;
63
64
65
66
67
68
69 public class ScmBranchPhaseTest extends AbstractReleaseTestCase {
70 @Override
71 public void setUp() throws Exception {
72 super.setUp();
73
74 phase = lookup(ReleasePhase.class, "scm-branch");
75 }
76
77 public static String getPath(File file) throws IOException {
78 return file.toPath().toRealPath(LinkOption.NOFOLLOW_LINKS).toString();
79 }
80
81 @Test
82 public void testBranch() throws Exception {
83
84 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
85 List<MavenProject> reactorProjects = createReactorProjects();
86 builder.setScmSourceUrl("scm-url");
87 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
88 builder.setWorkingDirectory(getPath(rootProject.getFile().getParentFile()));
89 builder.setPomFileName("pom.xml");
90 builder.setScmReleaseLabel("release-label");
91 builder.setScmCommentPrefix("[my prefix] ");
92
93 ScmFileSet fileSet = new ScmFileSet(rootProject.getFile().getParentFile());
94
95 ScmProvider scmProviderMock = mock(ScmProvider.class);
96 when(scmProviderMock.branch(
97 isA(ScmRepository.class),
98 argThat(new IsScmFileSetEquals(fileSet)),
99 eq("release-label"),
100 argThat(new IsScmBranchParametersEquals(
101 new ScmBranchParameters("[my prefix] copy for branch release-label")))))
102 .thenReturn(new BranchScmResult(
103 "...",
104 Collections.singletonList(new ScmFile(getPath(rootProject.getFile()), ScmFileStatus.TAGGED))));
105 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
106 stub.setScmProvider(scmProviderMock);
107
108
109 phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
110
111
112 verify(scmProviderMock)
113 .branch(
114 isA(ScmRepository.class),
115 argThat(new IsScmFileSetEquals(fileSet)),
116 eq("release-label"),
117 argThat(new IsScmBranchParametersEquals(
118 new ScmBranchParameters("[my prefix] copy for branch release-label"))));
119 verifyNoMoreInteractions(scmProviderMock);
120 }
121
122 @Test
123 public void testCommitMultiModuleDeepFolders() throws Exception {
124
125 String dir = "scm-commit/multimodule-with-deep-subprojects";
126 List<MavenProject> reactorProjects = createReactorProjects(dir, dir, null);
127 String sourceUrl = "http://svn.example.com/repos/project/trunk/";
128 String scmUrl = "scm:svn:" + sourceUrl;
129 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
130 builder.setScmSourceUrl(scmUrl);
131 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
132 builder.setWorkingDirectory(getPath(rootProject.getFile().getParentFile()));
133 builder.setPomFileName("pom.xml");
134 builder.setScmReleaseLabel("release-label");
135 builder.setScmCommentPrefix("[my prefix] ");
136 builder.setScmBranchBase("http://svn.example.com/repos/project/branches/");
137
138 ScmFileSet fileSet = new ScmFileSet(rootProject.getFile().getParentFile());
139
140 SvnScmProviderRepository scmProviderRepository = new SvnScmProviderRepository(sourceUrl);
141 scmProviderRepository.setBranchBase("http://svn.example.com/repos/project/branches/");
142 ScmRepository repository = new ScmRepository("svn", scmProviderRepository);
143 ScmProvider scmProviderMock = mock(ScmProvider.class);
144 when(scmProviderMock.branch(
145 eq(repository),
146 argThat(new IsScmFileSetEquals(fileSet)),
147 eq("release-label"),
148 argThat(new IsScmBranchParametersEquals(
149 new ScmBranchParameters("[my prefix] copy for branch release-label")))))
150 .thenReturn(new BranchScmResult(
151 "...",
152 Collections.singletonList(new ScmFile(getPath(rootProject.getFile()), ScmFileStatus.TAGGED))));
153
154 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
155 stub.setScmProvider(scmProviderMock);
156 stub.addScmRepositoryForUrl(scmUrl, repository);
157
158
159 phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
160
161
162 verify(scmProviderMock)
163 .branch(
164 eq(repository),
165 argThat(new IsScmFileSetEquals(fileSet)),
166 eq("release-label"),
167 argThat(new IsScmBranchParametersEquals(
168 new ScmBranchParameters("[my prefix] copy for branch release-label"))));
169 verifyNoMoreInteractions(scmProviderMock);
170 }
171
172 @Test
173 public void testCommitForFlatMultiModule() throws Exception {
174
175 List<MavenProject> reactorProjects =
176 createReactorProjects("rewrite-for-release/pom-with-parent-flat", "root-project");
177 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
178 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
179 builder.setScmSourceUrl(rootProject.getScm().getConnection());
180 builder.setWorkingDirectory(getWorkingDirectory("rewrite-for-release/pom-with-parent-flat")
181 .toRealPath(LinkOption.NOFOLLOW_LINKS)
182 .toString());
183 builder.setPomFileName("root-project/pom.xml");
184 builder.setScmReleaseLabel("release-label");
185 builder.setScmCommentPrefix("[my prefix] ");
186
187
188 ScmFileSet fileSet =
189 new ScmFileSet(rootProject.getFile().getParentFile().getParentFile());
190
191 String scmUrl = "file://localhost/tmp/scm-repo/trunk";
192 SvnScmProviderRepository scmProviderRepository = new SvnScmProviderRepository(scmUrl);
193 ScmRepository repository = new ScmRepository("svn", scmProviderRepository);
194 ScmProvider scmProviderMock = mock(ScmProvider.class);
195 when(scmProviderMock.branch(
196 eq(repository),
197 argThat(new IsScmFileSetEquals(fileSet)),
198 eq("release-label"),
199 argThat(new IsScmBranchParametersEquals(
200 new ScmBranchParameters("[my prefix] copy for branch release-label")))))
201 .thenReturn(new BranchScmResult(
202 "...",
203 Collections.singletonList(new ScmFile(getPath(rootProject.getFile()), ScmFileStatus.TAGGED))));
204
205 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
206 stub.setScmProvider(scmProviderMock);
207 stub.addScmRepositoryForUrl("scm:svn:" + scmUrl, repository);
208
209
210 phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
211
212
213 verify(scmProviderMock)
214 .branch(
215 eq(repository),
216 argThat(new IsScmFileSetEquals(fileSet)),
217 eq("release-label"),
218 argThat(new IsScmBranchParametersEquals(
219 new ScmBranchParameters("[my prefix] copy for branch release-label"))));
220 verifyNoMoreInteractions(scmProviderMock);
221 }
222
223 @Test
224 public void testCommitMultiModule() throws Exception {
225
226 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
227 String dir = "scm-commit/multiple-poms";
228 List<MavenProject> reactorProjects = createReactorProjects(dir, dir, null);
229 builder.setScmSourceUrl("scm-url");
230 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
231 builder.setWorkingDirectory(getPath(rootProject.getFile().getParentFile()));
232 builder.setPomFileName("pom.xml");
233 builder.setScmReleaseLabel("release-label");
234 builder.setScmCommentPrefix("[my prefix] ");
235
236 ScmFileSet fileSet = new ScmFileSet(rootProject.getFile().getParentFile());
237
238 ScmProvider scmProviderMock = mock(ScmProvider.class);
239 when(scmProviderMock.branch(
240 isA(ScmRepository.class),
241 argThat(new IsScmFileSetEquals(fileSet)),
242 eq("release-label"),
243 argThat(new IsScmBranchParametersEquals(
244 new ScmBranchParameters("[my prefix] copy for branch release-label")))))
245 .thenReturn(new BranchScmResult(
246 "...",
247 Collections.singletonList(new ScmFile(getPath(rootProject.getFile()), ScmFileStatus.TAGGED))));
248
249 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
250 stub.setScmProvider(scmProviderMock);
251
252
253 phase.execute(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
254
255
256 verify(scmProviderMock)
257 .branch(
258 isA(ScmRepository.class),
259 argThat(new IsScmFileSetEquals(fileSet)),
260 eq("release-label"),
261 argThat(new IsScmBranchParametersEquals(
262 new ScmBranchParameters("[my prefix] copy for branch release-label"))));
263 verifyNoMoreInteractions(scmProviderMock);
264 }
265
266 @Test
267 public void testBranchNoReleaseLabel() throws Exception {
268 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
269 List<MavenProject> reactorProjects = createReactorProjects();
270
271 try {
272 phase.execute(
273 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
274 fail("Should have thrown an exception");
275 } catch (ReleaseFailureException e) {
276 assertTrue(true);
277 }
278 }
279
280 @Test
281 public void testSimulateBranch() throws Exception {
282 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
283 List<MavenProject> reactorProjects = createReactorProjects();
284 builder.setScmSourceUrl("scm-url");
285 MavenProject rootProject = ReleaseUtil.getRootProject(reactorProjects);
286 builder.setWorkingDirectory(getPath(rootProject.getFile().getParentFile()));
287 builder.setPomFileName("pom.xml");
288 builder.setScmReleaseLabel("release-label");
289
290 ScmProvider scmProviderMock = mock(ScmProvider.class);
291
292 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
293 stub.setScmProvider(scmProviderMock);
294
295
296 phase.simulate(ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
297
298
299
300 verifyNoMoreInteractions(scmProviderMock);
301 }
302
303 @Test
304 public void testSimulateBranchNoReleaseLabel() throws Exception {
305 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
306 List<MavenProject> reactorProjects = createReactorProjects();
307
308 try {
309 phase.simulate(
310 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
311 fail("Should have thrown an exception");
312 } catch (ReleaseFailureException e) {
313 assertTrue(true);
314 }
315 }
316
317 @Test
318 public void testNoSuchScmProviderExceptionThrown() throws Exception {
319
320 List<MavenProject> reactorProjects = createReactorProjects();
321 ReleaseDescriptorBuilder builder = createReleaseDescriptorBuilder();
322
323 ScmManagerStub scmManagerStub = (ScmManagerStub) lookup(ScmManager.class);
324 scmManagerStub.setException(new NoSuchScmProviderException("..."));
325
326
327 try {
328 phase.execute(
329 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
330
331 fail("Status check should have failed");
332 } catch (ReleaseExecutionException e) {
333
334 assertEquals(
335 "check cause",
336 NoSuchScmProviderException.class,
337 e.getCause().getClass());
338 }
339 }
340
341 @Test
342 public void testScmRepositoryExceptionThrown() throws Exception {
343
344 List<MavenProject> reactorProjects = createReactorProjects();
345 ReleaseDescriptorBuilder builder = createReleaseDescriptorBuilder();
346
347 ScmManagerStub scmManagerStub = (ScmManagerStub) lookup(ScmManager.class);
348 scmManagerStub.setException(new ScmRepositoryException("..."));
349
350
351 try {
352 phase.execute(
353 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
354
355 fail("Status check should have failed");
356 } catch (ReleaseScmRepositoryException e) {
357
358 assertNull("Check no additional cause", e.getCause());
359 }
360 }
361
362 @Test
363 public void testScmExceptionThrown() throws Exception {
364
365 List<MavenProject> reactorProjects = createReactorProjects();
366 ReleaseDescriptorBuilder builder = createReleaseDescriptorBuilder();
367
368 ScmProvider scmProviderMock = mock(ScmProvider.class);
369 when(scmProviderMock.branch(
370 isA(ScmRepository.class),
371 isA(ScmFileSet.class),
372 isA(String.class),
373 isA(ScmBranchParameters.class)))
374 .thenThrow(new ScmException("..."));
375
376 ScmManagerStub stub = (ScmManagerStub) lookup(ScmManager.class);
377 stub.setScmProvider(scmProviderMock);
378
379
380 try {
381 phase.execute(
382 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
383
384 fail("Status check should have failed");
385 } catch (ReleaseExecutionException e) {
386 assertEquals("check cause", ScmException.class, e.getCause().getClass());
387 }
388
389
390 verify(scmProviderMock)
391 .branch(
392 isA(ScmRepository.class),
393 isA(ScmFileSet.class),
394 isA(String.class),
395 isA(ScmBranchParameters.class));
396 verifyNoMoreInteractions(scmProviderMock);
397 }
398
399 @Test
400 public void testScmResultFailure() throws Exception {
401 List<MavenProject> reactorProjects = createReactorProjects();
402 ReleaseDescriptorBuilder builder = createReleaseDescriptorBuilder();
403
404 ScmManager scmManager = lookup(ScmManager.class);
405 ScmProviderStub providerStub = (ScmProviderStub) scmManager.getProviderByUrl("scm-url");
406
407 providerStub.setBranchScmResult(new BranchScmResult("", "", "", false));
408
409 try {
410 phase.execute(
411 ReleaseUtils.buildReleaseDescriptor(builder), new DefaultReleaseEnvironment(), reactorProjects);
412
413 fail("Commit should have failed");
414 } catch (ReleaseScmCommandException e) {
415 assertNull("check no other cause", e.getCause());
416 }
417 }
418
419 private List<MavenProject> createReactorProjects() throws Exception {
420 String dir = "scm-commit/single-pom";
421 return createReactorProjects(dir, dir, null);
422 }
423
424 private static ReleaseDescriptorBuilder createReleaseDescriptorBuilder() throws IOException {
425 ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
426 builder.setScmSourceUrl("scm-url");
427 builder.setScmReleaseLabel("release-label");
428
429 File workingDir = getTestFile("target/test/checkout");
430 if (!workingDir.exists()) {
431 assertTrue(
432 "Failed to create the directory, along with all necessary parent directories", workingDir.mkdirs());
433 }
434
435 builder.setWorkingDirectory(getPath(workingDir));
436 builder.setPomFileName("pom.xml");
437 return builder;
438 }
439 }