1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.releaser.util.github;
35
36 import java.io.File;
37 import java.io.IOException;
38 import java.io.UnsupportedEncodingException;
39 import java.net.URLEncoder;
40 import java.text.MessageFormat;
41 import java.util.ArrayList;
42 import java.util.Collection;
43 import java.util.HashMap;
44 import java.util.Iterator;
45 import java.util.List;
46 import java.util.Map;
47
48 import org.apache.commons.lang3.StringUtils;
49 import org.eclipse.jgit.api.CloneCommand;
50 import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
51 import org.eclipse.jgit.api.ListBranchCommand.ListMode;
52 import org.eclipse.jgit.api.Git;
53 import org.eclipse.jgit.api.MergeResult;
54 import org.eclipse.jgit.api.PullResult;
55 import org.eclipse.jgit.api.errors.CanceledException;
56 import org.eclipse.jgit.api.errors.CheckoutConflictException;
57 import org.eclipse.jgit.api.errors.DetachedHeadException;
58 import org.eclipse.jgit.api.errors.GitAPIException;
59 import org.eclipse.jgit.api.errors.InvalidConfigurationException;
60 import org.eclipse.jgit.api.errors.InvalidRefNameException;
61 import org.eclipse.jgit.api.errors.InvalidRemoteException;
62 import org.eclipse.jgit.api.errors.NoHeadException;
63 import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
64 import org.eclipse.jgit.api.errors.RefNotFoundException;
65 import org.eclipse.jgit.api.errors.TransportException;
66 import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
67 import org.eclipse.jgit.lib.Ref;
68 import org.eclipse.jgit.lib.Repository;
69 import org.eclipse.jgit.revwalk.RevCommit;
70 import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
71 import org.eclipse.jgit.transport.CredentialsProvider;
72 import org.eclipse.jgit.transport.RefSpec;
73 import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
74
75 import fr.paris.lutece.plugins.releaser.util.CommandResult;
76 import fr.paris.lutece.plugins.releaser.util.ConstanteUtils;
77 import fr.paris.lutece.plugins.releaser.util.MapperJsonUtil;
78 import fr.paris.lutece.plugins.releaser.util.ReleaserUtils;
79 import fr.paris.lutece.portal.service.util.AppLogService;
80 import fr.paris.lutece.portal.service.util.AppPropertiesService;
81 import fr.paris.lutece.util.httpaccess.HttpAccess;
82 import fr.paris.lutece.util.httpaccess.HttpAccessException;
83 import fr.paris.lutece.util.signrequest.BasicAuthorizationAuthenticator;
84
85
86
87
88
89 public class GitUtils
90 {
91
92
93 public static final String MASTER_BRANCH = "master";
94
95
96 public static final String DEFAULT_RELEASE_BRANCH = "develop";
97
98
99 private static final String CONSTANTE_REF_TAG = "refs/tags/";
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 public static Git cloneRepo( String sClonePath, String sRepoURL, CommandResult commandResult, String strGitHubUserLogin, String strUserName,
119 String strPassword )
120 {
121 Git git = null;
122 Repository repository = null;
123 try
124 {
125 FileRepositoryBuilder builder = new FileRepositoryBuilder( );
126 File fGitDir = new File( sClonePath );
127
128 CloneCommand clone = Git.cloneRepository( ).setCredentialsProvider( new UsernamePasswordCredentialsProvider( strUserName, strPassword ) )
129 .setBare( false ).setCloneAllBranches( true ).setDirectory( fGitDir ).setURI( getRepoUrl( sRepoURL ) );
130
131 git = clone.call( );
132
133 repository = builder.setGitDir( fGitDir ).readEnvironment( ).findGitDir( ).build( );
134 repository.getConfig( ).setString( "user", null, "name", strGitHubUserLogin );
135 repository.getConfig( ).setString( "user", null, "email", strGitHubUserLogin + "@users.noreply.github.com" );
136 repository.getConfig( ).save( );
137
138 }
139 catch( InvalidRemoteException e )
140 {
141
142 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
143
144 }
145 catch( TransportException e )
146 {
147 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
148
149 }
150 catch( IOException e )
151 {
152 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
153 }
154 catch( GitAPIException e )
155 {
156
157 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
158 }
159 finally
160 {
161 if ( repository != null )
162 {
163 repository.close( );
164 }
165 }
166 return git;
167
168 }
169
170
171
172
173
174
175
176
177
178
179
180 public static void checkoutRepoBranch( Git git, String sBranchName, CommandResult commandResult )
181 {
182 try
183 {
184 git.checkout( ).setName( sBranchName ).call( );
185
186 }
187 catch( InvalidRemoteException e )
188 {
189
190 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
191
192 }
193 catch( TransportException e )
194 {
195 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
196
197 }
198
199 catch( GitAPIException e )
200 {
201 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
202 }
203
204 }
205
206
207
208
209
210
211
212
213
214
215
216 public static void createLocalBranch( Git git, String sBranchName, CommandResult commandResult )
217 {
218 try
219 {
220 git.branchCreate( ).setName( sBranchName ).setUpstreamMode( SetupUpstreamMode.SET_UPSTREAM ).setStartPoint( "origin/" + sBranchName )
221 .setForce( true ).call( );
222 }
223 catch( InvalidRemoteException e )
224 {
225
226 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
227
228 }
229 catch( TransportException e )
230 {
231 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
232
233 }
234
235 catch( GitAPIException e )
236 {
237 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
238 }
239
240 }
241
242
243
244
245
246
247
248
249
250
251
252
253 public static String getRefBranch( Git git, String sBranchName, CommandResult commandResult )
254 {
255
256 String refLastCommit = null;
257 try
258 {
259 git.checkout( ).setName( sBranchName ).call( );
260 refLastCommit = getLastCommitId( git );
261 }
262
263 catch( RefAlreadyExistsException e )
264 {
265 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
266 }
267 catch( RefNotFoundException e )
268 {
269 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
270 }
271 catch( InvalidRefNameException e )
272 {
273 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
274 }
275 catch( CheckoutConflictException e )
276 {
277 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
278 }
279 catch( GitAPIException e )
280 {
281 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
282 }
283 return refLastCommit;
284 }
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304 public static void pushForce( Git git, String strRefSpec, String strUserName, String strPassword )
305 throws InvalidRemoteException, TransportException, GitAPIException
306 {
307
308 git.push( ).setRemote( "origin" ).setRefSpecs( new RefSpec( strRefSpec ) ).setForce( true )
309 .setCredentialsProvider( new UsernamePasswordCredentialsProvider( strUserName, strPassword ) ).call( );
310
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346 public static PullResult pullRepoBranch( Git git, String sBranchName, String strUserName, String strPassword )
347 throws IOException, WrongRepositoryStateException, InvalidConfigurationException, DetachedHeadException, InvalidRemoteException, CanceledException,
348 RefNotFoundException, NoHeadException, TransportException, GitAPIException
349 {
350 PullResult pPullResult = git.pull( ).setCredentialsProvider( new UsernamePasswordCredentialsProvider( strUserName, strPassword ) ).setRemote( "origin" )
351 .setRemoteBranchName( sBranchName ).call( );
352
353 return pPullResult;
354 }
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385 public static MergeResult mergeRepoBranch( Git git, String strBranchToMerge )
386 throws IOException, WrongRepositoryStateException, InvalidConfigurationException, DetachedHeadException, InvalidRemoteException, CanceledException,
387 RefNotFoundException, NoHeadException, TransportException, GitAPIException
388 {
389 List<Ref> call = git.branchList( ).call( );
390 Ref mergedBranchRef = null;
391 for ( Ref ref : call )
392 {
393 if ( ref.getName( ).equals( "refs/heads/" + strBranchToMerge ) )
394 {
395 mergedBranchRef = ref;
396 break;
397 }
398 }
399 MergeResult mergeResult = git.merge( ).include( mergedBranchRef ).call( );
400 return mergeResult;
401 }
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416 public static String getLastLog( Git git, int nMaxCommit ) throws NoHeadException, GitAPIException
417 {
418 Iterable<RevCommit> logList = git.log( ).setMaxCount( 1 ).call( );
419 Iterator i = logList.iterator( );
420 String sCommitMessages = "";
421 while ( i.hasNext( ) )
422 {
423 RevCommit revCommit = (RevCommit) i.next( );
424 sCommitMessages += revCommit.getFullMessage( );
425 sCommitMessages += "\n";
426 sCommitMessages += revCommit.getCommitterIdent( );
427 }
428 return sCommitMessages;
429 }
430
431
432
433
434
435
436
437
438
439
440
441
442 public static String getLastCommitId( Git git ) throws NoHeadException, GitAPIException
443 {
444 Iterable<RevCommit> logList = git.log( ).setMaxCount( 1 ).call( );
445 Iterator i = logList.iterator( );
446 String strCommitId = null;
447 while ( i.hasNext( ) )
448 {
449 RevCommit revCommit = (RevCommit) i.next( );
450 strCommitId = revCommit.getName( );
451
452 }
453 return strCommitId;
454 }
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473 public static MergeResult mergeBack( Git git, String strUserName, String strPassword, CommandResult commandResult ) throws IOException, GitAPIException
474 {
475
476 Ref tag = getTagLinkedToLastRelease( git );
477
478 git.checkout( ).setName( MASTER_BRANCH ).call( );
479 List<Ref> call = git.branchList( ).call( );
480
481 Ref mergedBranchRef = null;
482 for ( Ref ref : call )
483 {
484 if ( ref.getName( ).equals( "refs/heads/" + DEFAULT_RELEASE_BRANCH ) )
485 {
486 mergedBranchRef = ref;
487 break;
488 }
489 }
490
491 if ( tag != null )
492 {
493 mergedBranchRef = tag;
494 }
495 MergeResult mergeResult = git.merge( ).include( mergedBranchRef ).call( );
496 if ( mergeResult.getMergeStatus( ).equals( MergeResult.MergeStatus.CHECKOUT_CONFLICT )
497 || mergeResult.getMergeStatus( ).equals( MergeResult.MergeStatus.CONFLICTING )
498 || mergeResult.getMergeStatus( ).equals( MergeResult.MergeStatus.FAILED )
499 || mergeResult.getMergeStatus( ).equals( MergeResult.MergeStatus.NOT_SUPPORTED ) )
500 {
501
502 ReleaserUtils.addTechnicalError( commandResult,
503 mergeResult.getMergeStatus( ).toString( ) + "\nPlease merge manually master into" + DEFAULT_RELEASE_BRANCH + "branch." );
504 }
505 else
506 {
507 git.push( ).setCredentialsProvider( new UsernamePasswordCredentialsProvider( strUserName, strPassword ) ).call( );
508 commandResult.getLog( ).append( mergeResult.getMergeStatus( ) );
509 }
510 return mergeResult;
511
512 }
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527 public static GithubSearchResult searchRepo( String strSearch, String strOrganization, String strUserName, String strPassword )
528 {
529 HttpAccess httpAccess = new HttpAccess( );
530
531 GithubSearchResult searchResult = null;
532
533 String strUrl = null;
534 try
535 {
536 strUrl = MessageFormat.format( AppPropertiesService.getProperty( ConstanteUtils.PROPERTY_GITHUB_SEARCH_REPO_API ),
537 URLEncoder.encode( strSearch, "UTF-8" ), strOrganization );
538 }
539 catch( UnsupportedEncodingException e1 )
540 {
541 AppLogService.error( e1 );
542 }
543
544 String strResponse = "";
545
546 try
547 {
548
549 String strApiToken = AppPropertiesService.getProperty( ConstanteUtils.PROPERTY_GITHUB_SEARCH_REPO_API_TOKEN );
550 Map<String, String> mapHeaderToken = new HashMap<String, String>( );
551 mapHeaderToken.put( "Authorization", "token " + strApiToken );
552 strResponse = httpAccess.doGet( strUrl, null, null, mapHeaderToken );
553
554 if ( !StringUtils.isEmpty( strResponse ) )
555 {
556 searchResult = MapperJsonUtil.parse( strResponse, GithubSearchResult.class );
557
558 }
559
560 }
561 catch( HttpAccessException ex )
562 {
563 AppLogService.error( ex );
564 }
565 catch( IOException e )
566 {
567 AppLogService.error( e );
568 }
569
570 return searchResult;
571 }
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588 public static String getFileContent( String strFullName, String strPathFile, String strBranch, String strUserName, String strPassword )
589 {
590 HttpAccess httpAccess = new HttpAccess( );
591 String strUrl = "https://raw.githubusercontent.com/" + strFullName + "/" + strBranch + "/" + strPathFile;
592
593
594 String strResponse = "";
595
596 try
597 {
598
599 strResponse = httpAccess.doGet( strUrl, new BasicAuthorizationAuthenticator( strUserName, strPassword ), null );
600
601 }
602 catch( HttpAccessException ex )
603 {
604 AppLogService.error( ex );
605 }
606
607 return strResponse;
608 }
609
610
611
612
613
614
615
616
617
618
619 private static Ref getTagLinkedToLastRelease( Git git ) throws GitAPIException
620 {
621 final String TOKEN = "[maven-release-plugin] prepare release ";
622 Ref res = null;
623 String sTagName = null;
624
625 Iterable<RevCommit> logList = git.log( ).setMaxCount( 10 ).call( );
626 Iterator i = logList.iterator( );
627 String sCommitMessages = "";
628 while ( i.hasNext( ) )
629 {
630 RevCommit revCommit = (RevCommit) i.next( );
631
632 sCommitMessages = revCommit.getFullMessage( );
633 int index = sCommitMessages.indexOf( TOKEN );
634 if ( index >= 0 )
635 {
636 sTagName = sCommitMessages.replace( TOKEN, "" );
637 break;
638 }
639 }
640
641 if ( ( sTagName != null ) && ( !( sTagName.trim( ).equals( "" ) ) ) )
642 {
643 List<Ref> tags = git.tagList( ).call( );
644 for ( int j = 0; j < tags.size( ); j++ )
645 {
646 Ref tag = tags.get( tags.size( ) - 1 - j );
647 String tagName = tag.getName( );
648 if ( ( "refs/tags/" + sTagName ).startsWith( tag.getName( ) ) )
649 {
650 res = tag;
651 break;
652 }
653 }
654 }
655
656 return res;
657 }
658
659
660
661
662
663
664
665
666 public static List<String> getTagNameList( Git git )
667 {
668 List<String> listTagName = null;
669 if ( git != null )
670 {
671 listTagName = new ArrayList<>( );
672 Collection<Ref> colTags = git.getRepository( ).getTags( ).values( );
673 for ( Ref ref : colTags )
674 {
675 listTagName.add( ref.getName( ).replace( CONSTANTE_REF_TAG, "" ) );
676 }
677 }
678
679 return listTagName;
680 }
681
682
683
684
685
686
687
688
689 public static String getRepoUrl( String strRepoUrl )
690 {
691
692 if ( strRepoUrl != null && strRepoUrl.startsWith( "scm:git:" ) )
693 {
694 strRepoUrl = strRepoUrl.substring( 8 );
695
696 }
697
698 return strRepoUrl;
699
700 }
701
702
703
704
705
706
707
708
709 public static Git getGit( String strClonePath )
710 {
711 Git git = null;
712 Repository repository = null;
713
714 File fGitDir = new File( strClonePath + "/.git" );
715
716 if ( !fGitDir.exists( ) )
717 {
718 return null;
719 }
720
721 try
722 {
723 FileRepositoryBuilder builder = new FileRepositoryBuilder( );
724 repository = builder.setGitDir( fGitDir ).readEnvironment( ).findGitDir( ).build( );
725
726 git = new Git( repository );
727 }
728 catch( IOException e )
729 {
730 AppLogService.error( e.getMessage( ), e );
731 }
732
733 return git;
734 }
735
736 public static List<String> getBranchList( String repoUrl, File localRepo, CommandResult commandResult, String login, String pwd )
737 {
738 Git git = null;
739 List<String> branchNameList = null;
740
741 try
742 {
743 CredentialsProvider credential = new UsernamePasswordCredentialsProvider( login, pwd );
744
745 git = Git.cloneRepository( ).setCredentialsProvider( credential ).setURI( repoUrl ).setDirectory( localRepo ).setCloneAllBranches( true ).call( );
746
747 branchNameList = new ArrayList<String>( );
748
749 List<Ref> branchList = git.branchList( ).setListMode( ListMode.ALL ).call( );
750 if ( !branchList.isEmpty( ) )
751 {
752 for ( Ref ref : branchList )
753 {
754 String [ ] refSplit = ref.getName( ).split( "/" );
755
756 if ( refSplit [1].equals( "remotes" ) && refSplit [2].equals( "origin" ) )
757 {
758 branchNameList.add( refSplit [3] );
759 }
760 }
761 }
762 }
763 catch( InvalidRemoteException e )
764 {
765 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
766 branchNameList.add( "InvalidRemoteException" );
767 }
768 catch( TransportException e )
769 {
770 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
771 branchNameList.add( "TransportException" );
772 }
773 catch( GitAPIException e )
774 {
775 ReleaserUtils.addTechnicalError( commandResult, e.getMessage( ), e );
776 branchNameList.add( "GitAPIException)" );
777 }
778 finally
779 {
780 if ( git != null )
781 {
782 git.close( );
783 }
784 }
785
786 return branchNameList;
787 }
788 }