11package org .scm4j .vcs .svn ;
22
3+ import java .io .ByteArrayOutputStream ;
4+ import java .io .File ;
5+ import java .io .FileWriter ;
6+ import java .io .UnsupportedEncodingException ;
7+ import java .nio .charset .StandardCharsets ;
8+ import java .util .ArrayList ;
9+ import java .util .Collection ;
10+ import java .util .Collections ;
11+ import java .util .HashSet ;
12+ import java .util .Iterator ;
13+ import java .util .List ;
14+ import java .util .Set ;
15+
316import org .apache .commons .io .FileUtils ;
4- import org .scm4j .vcs .api .*;
17+ import org .scm4j .vcs .api .IVCS ;
18+ import org .scm4j .vcs .api .VCSChangeType ;
19+ import org .scm4j .vcs .api .VCSCommit ;
20+ import org .scm4j .vcs .api .VCSDiffEntry ;
21+ import org .scm4j .vcs .api .VCSMergeResult ;
22+ import org .scm4j .vcs .api .VCSTag ;
23+ import org .scm4j .vcs .api .WalkDirection ;
524import org .scm4j .vcs .api .exceptions .EVCSBranchExists ;
625import org .scm4j .vcs .api .exceptions .EVCSException ;
726import org .scm4j .vcs .api .exceptions .EVCSFileNotFound ;
27+ import org .scm4j .vcs .api .exceptions .EVCSTagExists ;
828import org .scm4j .vcs .api .workingcopy .IVCSLockedWorkingCopy ;
929import org .scm4j .vcs .api .workingcopy .IVCSRepositoryWorkspace ;
1030import org .scm4j .vcs .api .workingcopy .IVCSWorkspace ;
11- import org .tmatesoft .svn .core .*;
31+ import org .tmatesoft .svn .core .ISVNLogEntryHandler ;
32+ import org .tmatesoft .svn .core .SVNCommitInfo ;
33+ import org .tmatesoft .svn .core .SVNDepth ;
34+ import org .tmatesoft .svn .core .SVNDirEntry ;
35+ import org .tmatesoft .svn .core .SVNException ;
36+ import org .tmatesoft .svn .core .SVNLogEntry ;
37+ import org .tmatesoft .svn .core .SVNLogEntryPath ;
38+ import org .tmatesoft .svn .core .SVNNodeKind ;
39+ import org .tmatesoft .svn .core .SVNProperties ;
40+ import org .tmatesoft .svn .core .SVNURL ;
1241import org .tmatesoft .svn .core .auth .BasicAuthenticationManager ;
1342import org .tmatesoft .svn .core .auth .SVNAuthentication ;
1443import org .tmatesoft .svn .core .auth .SVNPasswordAuthentication ;
1544import org .tmatesoft .svn .core .internal .wc .DefaultSVNOptions ;
1645import org .tmatesoft .svn .core .io .SVNRepository ;
1746import org .tmatesoft .svn .core .io .SVNRepositoryFactory ;
18- import org .tmatesoft .svn .core .wc .*;
19- import org .tmatesoft .svn .core .wc2 .*;
47+ import org .tmatesoft .svn .core .wc .ISVNConflictHandler ;
48+ import org .tmatesoft .svn .core .wc .ISVNOptions ;
49+ import org .tmatesoft .svn .core .wc .SVNClientManager ;
50+ import org .tmatesoft .svn .core .wc .SVNConflictChoice ;
51+ import org .tmatesoft .svn .core .wc .SVNConflictDescription ;
52+ import org .tmatesoft .svn .core .wc .SVNConflictResult ;
53+ import org .tmatesoft .svn .core .wc .SVNCopyClient ;
54+ import org .tmatesoft .svn .core .wc .SVNCopySource ;
55+ import org .tmatesoft .svn .core .wc .SVNDiffClient ;
56+ import org .tmatesoft .svn .core .wc .SVNInfo ;
57+ import org .tmatesoft .svn .core .wc .SVNRevision ;
58+ import org .tmatesoft .svn .core .wc .SVNRevisionRange ;
59+ import org .tmatesoft .svn .core .wc .SVNStatusType ;
60+ import org .tmatesoft .svn .core .wc .SVNUpdateClient ;
61+ import org .tmatesoft .svn .core .wc .SVNWCClient ;
62+ import org .tmatesoft .svn .core .wc .SVNWCUtil ;
63+ import org .tmatesoft .svn .core .wc2 .ISvnObjectReceiver ;
64+ import org .tmatesoft .svn .core .wc2 .SvnDiff ;
65+ import org .tmatesoft .svn .core .wc2 .SvnDiffStatus ;
66+ import org .tmatesoft .svn .core .wc2 .SvnDiffSummarize ;
67+ import org .tmatesoft .svn .core .wc2 .SvnOperationFactory ;
68+ import org .tmatesoft .svn .core .wc2 .SvnTarget ;
2069
2170import java .io .ByteArrayOutputStream ;
2271import java .io .File ;
@@ -40,10 +89,13 @@ public class SVNVCS implements IVCS {
4089 public static final String MASTER_PATH = "trunk/" ;
4190 public static final String BRANCHES_PATH = "branches/" ;
4291 public static final String SVN_VCS_TYPE_STRING = "svn" ;
92+ public static final String TAGS_PATH = "tags/" ;
93+ private static final String SVN_VCS_TYPE_STRING = "svn" ;
4394
4495 public void setClientManager (SVNClientManager clientManager ) {
4596 this .clientManager = clientManager ;
4697 }
98+
4799
48100 public SVNClientManager getClientManager () {
49101 return clientManager ;
@@ -585,4 +637,70 @@ public Boolean fileExists(String branchName, String filePath) {
585637 throw new RuntimeException (e );
586638 }
587639 }
640+
641+ @ Override
642+ public VCSTag createTag (String branchName , String tagName , String tagMessage ) throws EVCSTagExists {
643+ try {
644+ SVNURL srcURL = getBranchUrl (branchName );
645+ SVNURL dstURL = SVNURL .parseURIEncoded (repoUrl + TAGS_PATH + tagName );
646+ SVNCopySource copySource =
647+ new SVNCopySource (SVNRevision .HEAD , SVNRevision .HEAD , srcURL );
648+
649+ clientManager .getCopyClient ().doCopy (new SVNCopySource [] {copySource }, dstURL ,
650+ false , false , true , tagMessage , null );
651+
652+ SVNDirEntry entry = repository .info (TAGS_PATH + tagName , -1 );
653+
654+ VCSTag tag = new VCSTag (tagName , tagMessage , entry .getAuthor (), getHeadCommit (branchName ));
655+ return tag ;
656+ } catch (SVNException e ) {
657+ if (e .getErrorMessage ().getErrorCode ().getCode () == SVN_ITEM_EXISTS_ERROR_CODE ) {
658+ throw new EVCSTagExists (e );
659+ }
660+ throw new EVCSException (e );
661+ } catch (Exception e ) {
662+ throw new RuntimeException (e );
663+ }
664+ }
665+
666+ @ Override
667+ public List <VCSTag > getTags () {
668+ Set <String > entries = new HashSet <>();
669+ try {
670+ listEntries (entries , TAGS_PATH );
671+ List <VCSTag > res = new ArrayList <>();
672+ for (String entryStr : entries ) {
673+ SVNDirEntry entry = repository .info (entryStr , -1 );
674+ SVNInfo info = clientManager .getWCClient ().doInfo (SVNURL .parseURIEncoded (repoUrl + entryStr ), SVNRevision .HEAD , SVNRevision .HEAD );
675+
676+ info .getCommittedRevision (); // tag revision number
677+
678+ class SVNTagBaseCommit implements ISVNLogEntryHandler {
679+
680+ public Long copyFromRevision ;
681+
682+ @ Override
683+ public void handleLogEntry (SVNLogEntry logEntry ) throws SVNException {
684+ for (Iterator <?> changedPaths = logEntry .getChangedPaths ().keySet ().iterator (); changedPaths .hasNext ();) {
685+ SVNLogEntryPath entryPath = (SVNLogEntryPath ) logEntry .getChangedPaths ().get (changedPaths .next ());
686+ copyFromRevision = entryPath .getCopyRevision ();
687+ }
688+ }
689+ }
690+
691+ SVNTagBaseCommit handler = new SVNTagBaseCommit ();
692+
693+ repository .log (new String [] { entryStr }, -1 /* start from head descending */ ,
694+ 0 , true , true , -1 , handler );
695+
696+ SVNDirEntry copyFromEntry = repository .info ("" , handler .copyFromRevision );
697+
698+ res .add (new VCSTag (entry .getName (), entry .getCommitMessage (), entry .getAuthor (), new VCSCommit (Long .toString (copyFromEntry .getRevision ()),
699+ copyFromEntry .getCommitMessage (), copyFromEntry .getAuthor ())));
700+ }
701+ return res ;
702+ } catch (SVNException e ) {
703+ throw new EVCSException (e );
704+ }
705+ }
588706}
0 commit comments