1 package org.apache.maven.scm.provider.git.jgit.command;
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.scm.ScmFile;
23 import org.apache.maven.scm.ScmFileSet;
24 import org.apache.maven.scm.ScmFileStatus;
25 import org.apache.maven.scm.log.ScmLogger;
26 import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
27 import org.apache.maven.scm.util.FilenameUtils;
28 import org.codehaus.plexus.util.StringUtils;
29 import org.eclipse.jgit.api.AddCommand;
30 import org.eclipse.jgit.api.Git;
31 import org.eclipse.jgit.api.Status;
32 import org.eclipse.jgit.api.errors.GitAPIException;
33 import org.eclipse.jgit.api.errors.InvalidRemoteException;
34 import org.eclipse.jgit.api.errors.NoFilepatternException;
35 import org.eclipse.jgit.api.errors.TransportException;
36 import org.eclipse.jgit.diff.DiffEntry;
37 import org.eclipse.jgit.diff.DiffEntry.ChangeType;
38 import org.eclipse.jgit.diff.DiffFormatter;
39 import org.eclipse.jgit.diff.RawTextComparator;
40 import org.eclipse.jgit.errors.CorruptObjectException;
41 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
42 import org.eclipse.jgit.errors.MissingObjectException;
43 import org.eclipse.jgit.errors.StopWalkException;
44 import org.eclipse.jgit.lib.Constants;
45 import org.eclipse.jgit.lib.ObjectId;
46 import org.eclipse.jgit.lib.ProgressMonitor;
47 import org.eclipse.jgit.lib.Repository;
48 import org.eclipse.jgit.lib.StoredConfig;
49 import org.eclipse.jgit.lib.TextProgressMonitor;
50 import org.eclipse.jgit.revwalk.RevCommit;
51 import org.eclipse.jgit.revwalk.RevFlag;
52 import org.eclipse.jgit.revwalk.RevSort;
53 import org.eclipse.jgit.revwalk.RevWalk;
54 import org.eclipse.jgit.revwalk.filter.CommitTimeRevFilter;
55 import org.eclipse.jgit.revwalk.filter.RevFilter;
56 import org.eclipse.jgit.transport.CredentialsProvider;
57 import org.eclipse.jgit.transport.PushResult;
58 import org.eclipse.jgit.transport.RefSpec;
59 import org.eclipse.jgit.transport.RemoteRefUpdate;
60 import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
61 import org.eclipse.jgit.util.io.DisabledOutputStream;
62
63 import java.io.File;
64 import java.io.IOException;
65 import java.net.URI;
66 import java.util.ArrayList;
67 import java.util.Collection;
68 import java.util.Date;
69 import java.util.HashSet;
70 import java.util.Iterator;
71 import java.util.List;
72 import java.util.Set;
73
74
75
76
77
78
79
80
81 public class JGitUtils
82 {
83
84 private JGitUtils()
85 {
86
87 }
88
89
90
91
92
93 public static void closeRepo( Git git )
94 {
95 if ( git != null && git.getRepository() != null )
96 {
97 git.getRepository().close();
98 }
99 }
100
101
102
103
104
105
106
107 public static ProgressMonitor getMonitor( ScmLogger logger )
108 {
109
110 return new TextProgressMonitor();
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125 public static CredentialsProvider prepareSession( ScmLogger logger, Git git, GitScmProviderRepository repository )
126 {
127 StoredConfig config = git.getRepository().getConfig();
128 config.setString( "remote", "origin", "url", repository.getFetchUrl() );
129 config.setString( "remote", "origin", "pushURL", repository.getPushUrl() );
130
131
132 String password =
133 StringUtils.isNotBlank( repository.getPassword() ) ? repository.getPassword().trim() : "no-pwd-defined";
134 logger.info( "fetch url: " + repository.getFetchUrl().replace( password, "******" ) );
135 logger.info( "push url: " + repository.getPushUrl().replace( password, "******" ) );
136 return getCredentials( repository );
137 }
138
139
140
141
142
143
144
145
146
147
148
149 public static CredentialsProvider getCredentials( GitScmProviderRepository repository )
150 {
151 if ( StringUtils.isNotBlank( repository.getUser() ) && StringUtils.isNotBlank( repository.getPassword() ) )
152 {
153 return new UsernamePasswordCredentialsProvider( repository.getUser().trim(),
154 repository.getPassword().trim() );
155 }
156 return null;
157 }
158
159 public static Iterable<PushResult> push( ScmLogger logger, Git git, GitScmProviderRepository repo, RefSpec refSpec )
160 throws GitAPIException, InvalidRemoteException, TransportException
161 {
162 CredentialsProvider credentials = JGitUtils.prepareSession( logger, git, repo );
163 Iterable<PushResult> pushResultList =
164 git.push().setCredentialsProvider( credentials ).setRefSpecs( refSpec ).call();
165 for ( PushResult pushResult : pushResultList )
166 {
167 Collection<RemoteRefUpdate> ru = pushResult.getRemoteUpdates();
168 for ( RemoteRefUpdate remoteRefUpdate : ru )
169 {
170 logger.info( remoteRefUpdate.getStatus() + " - " + remoteRefUpdate.toString() );
171 }
172 }
173 return pushResultList;
174 }
175
176
177
178
179
180
181
182 public static boolean hasCommits( Repository repo )
183 {
184 if ( repo != null && repo.getDirectory().exists() )
185 {
186 return ( new File( repo.getDirectory(), "objects" ).list().length > 2 ) || (
187 new File( repo.getDirectory(), "objects/pack" ).list().length > 0 );
188 }
189 return false;
190 }
191
192
193
194
195
196
197
198
199
200
201
202
203 public static List<ScmFile> getFilesInCommit( Repository repository, RevCommit commit )
204 throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException
205 {
206 List<ScmFile> list = new ArrayList<ScmFile>();
207 if ( JGitUtils.hasCommits( repository ) )
208 {
209 RevWalk rw = new RevWalk( repository );
210 RevCommit realParant = commit.getParentCount() > 0 ? commit.getParent( 0 ) : commit;
211 RevCommit parent = rw.parseCommit( realParant.getId() );
212 DiffFormatter df = new DiffFormatter( DisabledOutputStream.INSTANCE );
213 df.setRepository( repository );
214 df.setDiffComparator( RawTextComparator.DEFAULT );
215 df.setDetectRenames( true );
216 List<DiffEntry> diffs = df.scan( parent.getTree(), commit.getTree() );
217 for ( DiffEntry diff : diffs )
218 {
219 list.add( new ScmFile( diff.getNewPath(), ScmFileStatus.CHECKED_IN ) );
220 }
221 rw.release();
222 }
223 return list;
224 }
225
226
227
228
229
230
231
232 public static ScmFileStatus getScmFileStatus( ChangeType changeType )
233 {
234 switch ( changeType )
235 {
236 case ADD:
237 return ScmFileStatus.ADDED;
238 case MODIFY:
239 return ScmFileStatus.MODIFIED;
240 case DELETE:
241 return ScmFileStatus.DELETED;
242 case RENAME:
243 return ScmFileStatus.RENAMED;
244 case COPY:
245 return ScmFileStatus.COPIED;
246 default:
247 return ScmFileStatus.UNKNOWN;
248 }
249 }
250
251
252
253
254
255
256
257
258
259
260
261 public static List<ScmFile> addAllFiles( Git git, ScmFileSet fileSet )
262 throws GitAPIException, NoFilepatternException
263 {
264 URI baseUri = fileSet.getBasedir().toURI();
265 AddCommand add = git.add();
266 for ( File file : fileSet.getFileList() )
267 {
268 if ( !file.isAbsolute() )
269 {
270 file = new File( fileSet.getBasedir().getPath(), file.getPath() );
271 }
272
273 if ( file.exists() )
274 {
275 String path = relativize( baseUri, file );
276 add.addFilepattern( path );
277 add.addFilepattern( file.getAbsolutePath() );
278 }
279 }
280 add.call();
281
282 Status status = git.status().call();
283
284 Set<String> allInIndex = new HashSet<String>();
285 allInIndex.addAll( status.getAdded() );
286 allInIndex.addAll( status.getChanged() );
287
288
289
290 List<ScmFile> addedFiles = new ArrayList<ScmFile>( allInIndex.size() );
291
292
293 for ( String entry : allInIndex )
294 {
295 ScmFile scmfile = new ScmFile( entry, ScmFileStatus.ADDED );
296
297
298
299 for ( Iterator<File> itfl = fileSet.getFileList().iterator(); itfl.hasNext(); )
300 {
301 String path = FilenameUtils.normalizeFilename( relativize( baseUri, itfl.next() ) );
302 if ( path.equals( FilenameUtils.normalizeFilename( scmfile.getPath() ) ) )
303 {
304 addedFiles.add( scmfile );
305 }
306 }
307 }
308 return addedFiles;
309 }
310
311 private static String relativize( URI baseUri, File f )
312 {
313 String path = f.getPath();
314 if ( f.isAbsolute() )
315 {
316 path = baseUri.relativize( new File( path ).toURI() ).getPath();
317 }
318 return path;
319 }
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336 public static List<RevCommit> getRevCommits( Repository repo, RevSort[] sortings, String fromRev, String toRev,
337 final Date fromDate, final Date toDate, int maxLines )
338 throws IOException, MissingObjectException, IncorrectObjectTypeException
339 {
340
341 List<RevCommit> revs = new ArrayList<RevCommit>();
342 RevWalk walk = new RevWalk( repo );
343
344 ObjectId fromRevId = fromRev != null ? repo.resolve( fromRev ) : null;
345 ObjectId toRevId = toRev != null ? repo.resolve( toRev ) : null;
346
347 if ( sortings == null || sortings.length == 0 )
348 {
349 sortings = new RevSort[]{ RevSort.TOPO, RevSort.COMMIT_TIME_DESC };
350 }
351
352 for ( final RevSort s : sortings )
353 {
354 walk.sort( s, true );
355 }
356
357 if ( fromDate != null && toDate != null )
358 {
359
360 walk.setRevFilter( new RevFilter()
361 {
362 @Override
363 public boolean include( RevWalk walker, RevCommit cmit )
364 throws StopWalkException, MissingObjectException, IncorrectObjectTypeException, IOException
365 {
366 int cmtTime = cmit.getCommitTime();
367
368 return ( cmtTime >= ( fromDate.getTime() / 1000 ) ) && ( cmtTime <= ( toDate.getTime() / 1000 ) );
369 }
370
371 @Override
372 public RevFilter clone()
373 {
374 return this;
375 }
376 } );
377 }
378 else
379 {
380 if ( fromDate != null )
381 {
382 walk.setRevFilter( CommitTimeRevFilter.after( fromDate ) );
383 }
384 if ( toDate != null )
385 {
386 walk.setRevFilter( CommitTimeRevFilter.before( toDate ) );
387 }
388 }
389
390 if ( fromRevId != null )
391 {
392 RevCommit c = walk.parseCommit( fromRevId );
393 c.add( RevFlag.UNINTERESTING );
394 RevCommit real = walk.parseCommit( c );
395 walk.markUninteresting( real );
396 }
397
398 if ( toRevId != null )
399 {
400 RevCommit c = walk.parseCommit( toRevId );
401 c.remove( RevFlag.UNINTERESTING );
402 RevCommit real = walk.parseCommit( c );
403 walk.markStart( real );
404 }
405 else
406 {
407 final ObjectId head = repo.resolve( Constants.HEAD );
408 if ( head == null )
409 {
410 throw new RuntimeException( "Cannot resolve " + Constants.HEAD );
411 }
412 RevCommit real = walk.parseCommit( head );
413 walk.markStart( real );
414 }
415
416 int n = 0;
417 for ( final RevCommit c : walk )
418 {
419 n++;
420 if ( maxLines != -1 && n > maxLines )
421 {
422 break;
423 }
424
425 revs.add( c );
426 }
427 return revs;
428 }
429
430 }