1 package org.apache.maven.plugins.scmpublish;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.commons.io.FileUtils;
23 import org.apache.commons.io.IOUtils;
24 import org.apache.commons.io.filefilter.NameFileFilter;
25 import org.apache.commons.io.filefilter.NotFileFilter;
26 import org.apache.maven.plugin.MojoExecutionException;
27 import org.apache.maven.plugin.MojoFailureException;
28 import org.apache.maven.plugins.annotations.Component;
29 import org.apache.maven.plugins.annotations.Mojo;
30 import org.apache.maven.plugins.annotations.Parameter;
31 import org.apache.maven.project.MavenProject;
32 import org.codehaus.plexus.util.MatchPatterns;
33
34 import java.io.BufferedReader;
35 import java.io.File;
36 import java.io.FileInputStream;
37 import java.io.FileOutputStream;
38 import java.io.IOException;
39 import java.io.InputStreamReader;
40 import java.io.OutputStreamWriter;
41 import java.io.PrintWriter;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.Collections;
45 import java.util.Date;
46 import java.util.HashSet;
47 import java.util.List;
48 import java.util.Set;
49
50
51
52
53
54
55 @Mojo ( name = "publish-scm", aggregator = true, requiresProject = false )
56 public class ScmPublishPublishScmMojo
57 extends AbstractScmPublishMojo
58 {
59
60
61
62 @Parameter ( property = "scmpublish.content", defaultValue = "${project.build.directory}/staging" )
63 private File content;
64
65
66
67 @Component
68 protected MavenProject project;
69
70 private List<File> deleted = new ArrayList<File>();
71
72 private List<File> added = new ArrayList<File>();
73
74 private List<File> updated = new ArrayList<File>();
75
76 private int directories = 0;
77 private int files = 0;
78 private long size = 0;
79
80
81
82
83
84
85
86
87
88
89 private void update( File checkout, File dir, List<String> doNotDeleteDirs )
90 throws IOException
91 {
92 String[] files =
93 checkout.list( new NotFileFilter( new NameFileFilter( scmProvider.getScmSpecificFilename() ) ) );
94
95 Set<String> checkoutContent = new HashSet<String>( Arrays.asList( files ) );
96 List<String> dirContent = ( dir != null ) ? Arrays.asList( dir.list() ) : Collections.<String>emptyList();
97
98 Set<String> deleted = new HashSet<String>( checkoutContent );
99 deleted.removeAll( dirContent );
100
101 MatchPatterns ignoreDeleteMatchPatterns = null;
102 List<String> pathsAsList = new ArrayList<String>( 0 );
103 if ( ignorePathsToDelete != null && ignorePathsToDelete.length > 0 )
104 {
105 ignoreDeleteMatchPatterns = MatchPatterns.from( ignorePathsToDelete );
106 pathsAsList = Arrays.asList( ignorePathsToDelete );
107 }
108
109 for ( String name : deleted )
110 {
111 if ( ignoreDeleteMatchPatterns != null && ignoreDeleteMatchPatterns.matches( name, true ) )
112 {
113 getLog().debug(
114 name + " match one of the patterns '" + pathsAsList + "': do not add to deleted files" );
115 continue;
116 }
117 getLog().debug( "file marked for deletion: " + name );
118 File file = new File( checkout, name );
119
120 if ( ( doNotDeleteDirs != null ) && file.isDirectory() && ( doNotDeleteDirs.contains( name ) ) )
121 {
122
123 continue;
124 }
125
126 if ( file.isDirectory() )
127 {
128 update( file, null, null );
129 }
130 this.deleted.add( file );
131 }
132
133 for ( String name : dirContent )
134 {
135 File file = new File( checkout, name );
136 File source = new File( dir, name );
137
138 if ( source.isDirectory() )
139 {
140 directories++;
141 if ( !checkoutContent.contains( name ) )
142 {
143 this.added.add( file );
144 file.mkdir();
145 }
146
147 update( file, source, null );
148 }
149 else
150 {
151 if ( checkoutContent.contains( name ) )
152 {
153 this.updated.add( file );
154 }
155 else
156 {
157 this.added.add( file );
158 }
159
160 copyFile( source, file );
161 }
162 }
163 }
164
165
166
167
168
169
170
171
172
173 private void copyFile( File srcFile, File destFile )
174 throws IOException
175 {
176 if ( requireNormalizeNewlines( srcFile ) )
177 {
178 copyAndNormalizeNewlines( srcFile, destFile );
179 }
180 else
181 {
182 FileUtils.copyFile( srcFile, destFile );
183 }
184 files++;
185 size += destFile.length();
186 }
187
188
189
190
191
192
193
194
195 private void copyAndNormalizeNewlines( File srcFile, File destFile )
196 throws IOException
197 {
198 BufferedReader in = null;
199 PrintWriter out = null;
200 try
201 {
202 in = new BufferedReader( new InputStreamReader( new FileInputStream( srcFile ), siteOutputEncoding ) );
203 out = new PrintWriter( new OutputStreamWriter( new FileOutputStream( destFile ), siteOutputEncoding ) );
204 String line;
205 while ( ( line = in.readLine() ) != null )
206 {
207 if ( in.ready() )
208 {
209 out.println( line );
210 }
211 else
212 {
213 out.print( line );
214 }
215 }
216 }
217 finally
218 {
219 IOUtils.closeQuietly( out );
220 IOUtils.closeQuietly( in );
221 }
222 }
223
224 public void scmPublishExecute()
225 throws MojoExecutionException, MojoFailureException
226 {
227 if ( siteOutputEncoding == null )
228 {
229 getLog().warn( "No output encoding, defaulting to UTF-8." );
230 siteOutputEncoding = "utf-8";
231 }
232
233 if ( !content.exists() )
234 {
235 throw new MojoExecutionException( "Configured content directory does not exist: " + content );
236 }
237
238 if ( !content.canRead() )
239 {
240 throw new MojoExecutionException( "Can't read content directory: " + content );
241 }
242
243 checkoutExisting();
244
245 try
246 {
247 logInfo( "Updating checkout directory with actual content in %s", content );
248 update( checkoutDirectory, content, ( project == null ) ? null : project.getModel().getModules() );
249 String displaySize = org.apache.commons.io.FileUtils.byteCountToDisplaySize( size );
250 logInfo( "Content consists in %d directories and %d files = %s", directories, files, displaySize );
251 }
252 catch ( IOException ioe )
253 {
254 throw new MojoExecutionException( "Could not copy content to SCM checkout", ioe );
255 }
256
257 logInfo( "Publishing content into SCM will result in %d addition(s), %d update(s), %d delete(s)", added.size(),
258 updated.size(), deleted.size() );
259
260 if ( isDryRun() )
261 {
262 int pos = checkoutDirectory.getAbsolutePath().length() + 1;
263 for ( File addedFile : added )
264 {
265 logInfo( "- addition %s", addedFile.getAbsolutePath().substring( pos ) );
266 }
267 for ( File updatedFile : updated )
268 {
269 logInfo( "- update %s", updatedFile.getAbsolutePath().substring( pos ) );
270 }
271 for ( File deletedFile : deleted )
272 {
273 logInfo( "- delete %s", deletedFile.getAbsolutePath().substring( pos ) );
274 }
275 return;
276 }
277
278 if ( !added.isEmpty() )
279 {
280 addFiles( added );
281 }
282
283 if ( !deleted.isEmpty() )
284 {
285 deleteFiles( deleted );
286 }
287
288 logInfo( "Checking in SCM, starting at " + new Date() + "..." );
289 checkinFiles();
290 }
291 }