1 package org.apache.maven.shared.release.phase;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.project.MavenProject;
23 import org.apache.maven.scm.ScmException;
24 import org.apache.maven.scm.ScmFile;
25 import org.apache.maven.scm.ScmFileSet;
26 import org.apache.maven.scm.command.status.StatusScmResult;
27 import org.apache.maven.scm.manager.NoSuchScmProviderException;
28 import org.apache.maven.scm.provider.ScmProvider;
29 import org.apache.maven.scm.repository.ScmRepository;
30 import org.apache.maven.scm.repository.ScmRepositoryException;
31 import org.apache.maven.shared.release.ReleaseExecutionException;
32 import org.apache.maven.shared.release.ReleaseFailureException;
33 import org.apache.maven.shared.release.ReleaseResult;
34 import org.apache.maven.shared.release.config.ReleaseDescriptor;
35 import org.apache.maven.shared.release.env.ReleaseEnvironment;
36 import org.apache.maven.shared.release.scm.ReleaseScmCommandException;
37 import org.apache.maven.shared.release.scm.ReleaseScmRepositoryException;
38 import org.apache.maven.shared.release.scm.ScmRepositoryConfigurator;
39 import org.apache.maven.shared.release.scm.ScmTranslator;
40 import org.codehaus.plexus.component.annotations.Component;
41 import org.codehaus.plexus.component.annotations.Requirement;
42 import org.codehaus.plexus.util.SelectorUtils;
43 import org.codehaus.plexus.util.StringUtils;
44
45 import java.io.File;
46 import java.util.Arrays;
47 import java.util.HashSet;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.Map;
51 import java.util.Set;
52
53
54
55
56
57
58 @Component( role = ReleasePhase.class, hint = "scm-check-modifications" )
59 public class ScmCheckModificationsPhase
60 extends AbstractReleasePhase
61 {
62
63
64
65 @Requirement
66 private ScmRepositoryConfigurator scmRepositoryConfigurator;
67
68
69
70
71 @Requirement( role = ScmTranslator.class )
72 private Map<String, ScmTranslator> scmTranslators;
73
74
75
76
77
78
79 private Set<String> exclusionPatterns = new HashSet<>( Arrays.asList(
80 "**" + File.separator + "pom.xml.backup", "**" + File.separator + "pom.xml.tag",
81 "**" + File.separator + "pom.xml.next", "**" + File.separator + "pom.xml.branch",
82 "**" + File.separator + "release.properties", "**" + File.separator + "pom.xml.releaseBackup" ) );
83
84 @Override
85 public ReleaseResult execute( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
86 List<MavenProject> reactorProjects )
87 throws ReleaseExecutionException, ReleaseFailureException
88 {
89 ReleaseResult relResult = new ReleaseResult();
90
91 List<String> additionalExcludes = releaseDescriptor.getCheckModificationExcludes();
92
93 if ( additionalExcludes != null )
94 {
95
96 for ( String additionalExclude : additionalExcludes )
97 {
98 exclusionPatterns.add( additionalExclude.replace( "\\", File.separator )
99 .replace( "/", File.separator ) );
100 }
101 }
102
103 logInfo( relResult, "Verifying that there are no local modifications..." );
104 logInfo( relResult, " ignoring changes on: " + StringUtils.join( exclusionPatterns.toArray(), ", " ) );
105
106 ScmRepository repository;
107 ScmProvider provider;
108 try
109 {
110 repository =
111 scmRepositoryConfigurator.getConfiguredRepository( releaseDescriptor,
112 releaseEnvironment.getSettings() );
113
114 provider = scmRepositoryConfigurator.getRepositoryProvider( repository );
115 }
116 catch ( ScmRepositoryException e )
117 {
118 throw new ReleaseScmRepositoryException( e.getMessage() + " for URL: "
119 + releaseDescriptor.getScmSourceUrl(), e.getValidationMessages() );
120 }
121 catch ( NoSuchScmProviderException e )
122 {
123 throw new ReleaseExecutionException( "Unable to configure SCM repository: " + e.getMessage(), e );
124 }
125
126 StatusScmResult result;
127 try
128 {
129 result =
130 provider.status( repository, new ScmFileSet( new File( releaseDescriptor.getWorkingDirectory() ) ) );
131 }
132 catch ( ScmException e )
133 {
134 throw new ReleaseExecutionException( "An error occurred during the status check process: " + e.getMessage(),
135 e );
136 }
137
138 if ( !result.isSuccess() )
139 {
140 throw new ReleaseScmCommandException( "Unable to check for local modifications", result );
141 }
142
143 List<ScmFile> changedFiles = result.getChangedFiles();
144
145 if ( !changedFiles.isEmpty() )
146 {
147 ScmTranslator scmTranslator = scmTranslators.get( repository.getProvider() );
148
149
150 for ( Iterator<ScmFile> i = changedFiles.iterator(); i.hasNext(); )
151 {
152 ScmFile f = i.next();
153
154 String path;
155 if ( scmTranslator != null )
156 {
157 path = scmTranslator.toRelativePath( f.getPath() );
158 }
159 else
160 {
161 path = f.getPath();
162 }
163
164
165 String fileName = path.replace( "\\", File.separator ).replace( "/", File.separator );
166
167 for ( String exclusionPattern : exclusionPatterns )
168 {
169 if ( SelectorUtils.matchPath( exclusionPattern, fileName ) )
170 {
171 logDebug( relResult, "Ignoring changed file: " + fileName );
172 i.remove();
173 break;
174 }
175 }
176 }
177 }
178
179 if ( !changedFiles.isEmpty() )
180 {
181 StringBuilder message = new StringBuilder();
182
183 for ( ScmFile file : changedFiles )
184 {
185 message.append( file.toString() );
186 message.append( "\n" );
187 }
188
189 throw new ReleaseFailureException( "Cannot prepare the release because you have local modifications : \n"
190 + message );
191 }
192
193 relResult.setResultCode( ReleaseResult.SUCCESS );
194
195 return relResult;
196 }
197
198 @Override
199 public ReleaseResult simulate( ReleaseDescriptor releaseDescriptor, ReleaseEnvironment releaseEnvironment,
200 List<MavenProject> reactorProjects )
201 throws ReleaseExecutionException, ReleaseFailureException
202 {
203
204 return execute( releaseDescriptor, releaseEnvironment, reactorProjects );
205 }
206 }