33import java .io .ByteArrayOutputStream ;
44import java .io .File ;
55import java .io .FileWriter ;
6+ import java .io .IOException ;
67import java .io .UnsupportedEncodingException ;
78import java .nio .charset .StandardCharsets ;
89import java .util .ArrayList ;
2021import org .tmatesoft .svn .core .SVNLogEntry ;
2122import org .tmatesoft .svn .core .SVNNodeKind ;
2223import org .tmatesoft .svn .core .SVNProperties ;
24+ import org .tmatesoft .svn .core .SVNRevisionProperty ;
2325import org .tmatesoft .svn .core .SVNURL ;
2426import org .tmatesoft .svn .core .auth .BasicAuthenticationManager ;
2527import org .tmatesoft .svn .core .auth .SVNAuthentication ;
2628import org .tmatesoft .svn .core .auth .SVNPasswordAuthentication ;
2729import org .tmatesoft .svn .core .internal .wc .DefaultSVNOptions ;
2830import org .tmatesoft .svn .core .io .SVNRepository ;
2931import org .tmatesoft .svn .core .io .SVNRepositoryFactory ;
32+ import org .tmatesoft .svn .core .wc .ISVNCommitParameters ;
3033import org .tmatesoft .svn .core .wc .ISVNConflictHandler ;
34+ import org .tmatesoft .svn .core .wc .ISVNDiffStatusHandler ;
3135import org .tmatesoft .svn .core .wc .ISVNOptions ;
36+ import org .tmatesoft .svn .core .wc .ISVNStatusHandler ;
3237import org .tmatesoft .svn .core .wc .SVNClientManager ;
3338import org .tmatesoft .svn .core .wc .SVNConflictChoice ;
3439import org .tmatesoft .svn .core .wc .SVNConflictDescription ;
40+ import org .tmatesoft .svn .core .wc .SVNConflictReason ;
3541import org .tmatesoft .svn .core .wc .SVNConflictResult ;
3642import org .tmatesoft .svn .core .wc .SVNCopyClient ;
3743import org .tmatesoft .svn .core .wc .SVNCopySource ;
3844import org .tmatesoft .svn .core .wc .SVNDiffClient ;
45+ import org .tmatesoft .svn .core .wc .SVNDiffStatus ;
3946import org .tmatesoft .svn .core .wc .SVNRevision ;
4047import org .tmatesoft .svn .core .wc .SVNRevisionRange ;
48+ import org .tmatesoft .svn .core .wc .SVNStatus ;
4149import org .tmatesoft .svn .core .wc .SVNStatusType ;
4250import org .tmatesoft .svn .core .wc .SVNUpdateClient ;
4351import org .tmatesoft .svn .core .wc .SVNWCClient ;
4452import org .tmatesoft .svn .core .wc .SVNWCUtil ;
45- import org .tmatesoft .svn .core .wc2 .ISvnObjectReceiver ;
4653import org .tmatesoft .svn .core .wc2 .SvnDiff ;
47- import org .tmatesoft .svn .core .wc2 .SvnDiffStatus ;
4854import org .tmatesoft .svn .core .wc2 .SvnDiffSummarize ;
4955import org .tmatesoft .svn .core .wc2 .SvnOperationFactory ;
5056import org .tmatesoft .svn .core .wc2 .SvnTarget ;
@@ -99,8 +105,10 @@ public SVNVCS(IVCSRepositoryWorkspace repo, String user, String password) {
99105 throw new EVCSException (e );
100106 }
101107
102- userPassAuth = SVNPasswordAuthentication .newInstance (user ,
103- (password == null ? null : password .toCharArray ()), true , trunkSVNUrl , false );
108+ // userPassAuth = SVNPasswordAuthentication.newInstance(user,
109+ // (password == null ? null : password.toCharArray()), true, trunkSVNUrl, false);
110+ userPassAuth = new SVNPasswordAuthentication (user ,
111+ (password == null ? null : password ), true , trunkSVNUrl , false );
104112 authManager = new BasicAuthenticationManager (new SVNAuthentication [] {userPassAuth });
105113 repository .setAuthenticationManager (authManager );
106114
@@ -113,7 +121,7 @@ public SVNRepository getRepository() {
113121 }
114122
115123 private SVNURL getBranchUrl (String branchPath ) throws SVNException {
116- return SVNURL .parseURIEncoded (repoUrl + ( branchPath == null ? MASTER_PATH : BRANCHES_PATH + branchPath ));
124+ return SVNURL .parseURIEncoded (repoUrl + getBranchPath ( branchPath ));
117125 }
118126
119127 private String getBranchPath (String branchPath ) {
@@ -140,7 +148,6 @@ public void createBranch(SVNURL fromUrl, SVNURL toUrl, String commitMessage) {
140148 SVNCopySource copySource = new SVNCopySource (SVNRevision .WORKING , SVNRevision .WORKING ,
141149 wc .getFolder ());
142150 copySource .setCopyContents (false );
143-
144151 copyClient .doCopy (new SVNCopySource [] { copySource }, toUrl ,
145152 false , // isMove
146153 true , // make parents
@@ -253,22 +260,25 @@ private boolean isWorkingCopyInited(File destPath) {
253260
254261 @ Override
255262 public void setCredentials (String user , String password ) {
256- userPassAuth = SVNPasswordAuthentication .newInstance (user , password .toCharArray (), true , trunkSVNUrl , false );
263+ // userPassAuth = SVNPasswordAuthentication.newInstance(user, password.toCharArray(), true, trunkSVNUrl, false);
264+ // authManager.setAuthentications(new SVNAuthentication[] {userPassAuth});
265+ userPassAuth = new SVNPasswordAuthentication (user , password , true , trunkSVNUrl , false );
257266 authManager .setAuthentications (new SVNAuthentication [] {userPassAuth });
267+
258268 }
259269
260270 @ Override
261271 public void setProxy (String host , int port , String proxyUser , String proxyPassword ) {
262- authManager .setProxy (host , port , proxyUser , proxyPassword . toCharArray () );
272+ authManager .setProxy (host , port , proxyUser , proxyPassword );
263273 }
264274
265275
266276 @ Override
267277 public String getFileContent (String branchName , String filePath , String encoding ) {
268278 ByteArrayOutputStream baos = new ByteArrayOutputStream ( );
269279 try {
270- repository .getFile (new File ((branchName == null ? MASTER_PATH : BRANCHES_PATH + branchName ),
271- filePath ) .getPath ().replace ("\\ " , "/" ), -1 , new SVNProperties (), baos );
280+ repository .getFile (new File (getBranchPath (branchName ), filePath )
281+ .getPath ().replace ("\\ " , "/" ), -1 , new SVNProperties (), baos );
272282 return baos .toString (encoding );
273283 } catch (SVNException e ) {
274284 if (e .getErrorMessage ().getErrorCode ().getCode () == SVN_FILE_NOT_FOUND_ERROR_CODE ) {
@@ -380,34 +390,247 @@ private List<VCSDiffEntry> getDiffEntries(final String srcBranchName, final Stri
380390 final SvnDiffSummarize summarizeDiff = svnOperationFactory .createDiffSummarize ();
381391 final List <VCSDiffEntry > res = new ArrayList <>();
382392
383- summarizeDiff .setSources (
384- SvnTarget .fromURL (getBranchUrl (dstBranchName ), SVNRevision .HEAD ),
385- SvnTarget .fromURL (getBranchUrl (srcBranchName ), SVNRevision .HEAD ));
393+ checkout (getBranchUrl (dstBranchName ), wc .getFolder ());
394+
395+ //SvnLogMergeInfo info = svnOperationFactory.createLogMergeInfo();
396+
397+ // info.setFindMerged(true);
398+ // info.setDepth(SVNDepth.INFINITY);
399+ // info.addRevisionRange(SvnRevisionRange.create(SVNRevision.create(1),
400+ // SVNRevision.create(repository.info(getBranchPath(srcBranchName), 13L).getRevision())));
401+ // info.setSource(SvnTarget.fromURL(getBranchUrl(dstBranchName)));
402+ // info.setSingleTarget(SvnTarget.fromFile(wc.getFolder()));
403+ // SVNLogEntry ent;
404+ // final Collection<SVNLogEntry> mergedRev s = new ArrayList<>();
405+ // clientManager.getDiffClient().doGetLogMergedMergeInfo(getBranchUrl(srcBranchName),
406+ // SVNRevision.HEAD, repository.getRepositoryRoot(true), SVNRevision.HEAD, true, null, new ISVNLogEntryHandler() {
407+ //
408+ // @Override
409+ // public void handleLogEntry(SVNLogEntry logEntry) throws SVNException {
410+ // mergedRevs.add(logEntry);
411+ //
412+ // }
413+ // });
414+ //
415+ //
416+ //
417+ // info.setReceiver(new ISvnObjectReceiver<SVNLogEntry>() {
418+ // @Override
419+ // public void receive(SvnTarget target, SVNLogEntry object) throws SVNException {
420+ // if (object.hasChildren()) {
421+ // mergedRevs.add(object);
422+ // }
423+ // }
424+ // });
425+ //
426+ //
427+ // info.run();
428+
429+
430+
431+
432+ // repository.log(new String[] { getBranchPath(srcBranchName) },
433+ // getBranchFirstCommit(srcBranchName).getRevision(), 0,
434+ // true, true, 0, new ISVNLogEntryHandler() {
435+ // @Override
436+ // public void handleLogEntry(SVNLogEntry logEntry) throws SVNException {
437+ // //res.add(logEntry.getRevision());
438+ // }
439+ // });
440+
441+ // Summarized Diff íå ïîäõîäèò, ò.ê. îí áóäåò ó÷èòûâàòü íåâìåðæåííûå êîìèòû òðàíêà.
442+ // Summarized Diff ïî êîììèòàì âåòêè ïîäîøåë áû, åñëè áû áûë ñïîñîá èñêëþ÷èòü êîììèòû, âìåðæåííûå èç òðàíêà
443+ // doStatus ïîñëå merge íå ïîäõîäèò, ò.ê. îí íå ìîæåò îïðåäåëèòü ñòàòóñ äëÿ file1.txt, êîòîðûé treeConflict
444+ // doStatus ñ÷èòàåò file1.txt unversioned, file3.txt âèäèò êàê normal, à íå added, folder\file3.txt - unknown
445+ // doStatus âèäèò file3.txt normal, a folder/ - added
446+ // doDiffStatus - åñëè ìåæäó ðåçóëüòàòîì ìåðäæà â òðàíê è òðàíêîì, òî ïðàâèëüíî, íî â èòîãå NPE
447+ // doDiffStatus - åñëè ìåæäó âåòêàìè, òî áóäóò âèäíû èçìåíåíèÿ òðàíêà, êîòîðûå íå óáðàòü
448+ // doDiffStatus - åñëè ìåæäó íà÷àëîì âåòêè è êîíöîì, òî îøèáêà "file not found: revision 15, path '/new-branch'"
449+
450+
451+ SVNDiffClient diffClient = clientManager .getDiffClient ();
386452
387- summarizeDiff .setReceiver (new ISvnObjectReceiver <SvnDiffStatus >() {
388- public void receive (SvnTarget target , SvnDiffStatus diffStatus ) throws SVNException {
389- if (diffStatus .getPath ().length () == 0 ) {
390- return ;
391- }
392- VCSDiffEntry entry = new VCSDiffEntry (diffStatus .getPath (),
393- SVNChangeTypeToVCSChangeType (diffStatus .getModificationType ()));
394- res .add (entry );
395- }
396453
397- private VCSChangeType SVNChangeTypeToVCSChangeType (SVNStatusType modificationType ) {
398- if (SVNStatusType .STATUS_ADDED .equals (modificationType )) {
399- return VCSChangeType .ADD ;
400- } else if (SVNStatusType .STATUS_DELETED .equals (modificationType )) {
401- return VCSChangeType .DELETE ;
402- } else if (SVNStatusType .STATUS_MODIFIED .equals (modificationType )) {
403- return VCSChangeType .MODIFY ;
404- } else {
405- return VCSChangeType .UNKNOWN ;
454+ DefaultSVNOptions options = (DefaultSVNOptions ) diffClient .getOptions ();
455+ options .setConflictHandler (new ISVNConflictHandler () {
456+ @ Override
457+ public SVNConflictResult handleConflict (SVNConflictDescription conflictDescription )
458+ throws SVNException {
459+ if (conflictDescription .getConflictReason () == SVNConflictReason .MISSING ) {
460+ File missingFile = conflictDescription .getMergeFiles ().getLocalFile ();
461+
462+ missingFile .getParentFile ().mkdirs ();
463+ try {
464+ missingFile .createNewFile ();
465+ String content = getFileContent (srcBranchName , conflictDescription .getMergeFiles ().getLocalPath ());
466+ FileUtils .writeStringToFile (missingFile , content );
467+ return new SVNConflictResult (SVNConflictChoice .MERGED , missingFile );
468+ } catch (IOException e ) {
469+ throw new RuntimeException (e );
470+ }
471+
406472 }
473+ return new SVNConflictResult (
474+ conflictDescription .isTreeConflict () ? SVNConflictChoice .POSTPONE : SVNConflictChoice .THEIRS_FULL ,
475+ conflictDescription .getMergeFiles ().getLocalFile ());
407476 }
408- });
477+ });
478+
479+
480+
481+ SVNRevisionRange range = new SVNRevisionRange (SVNRevision .create (1 ), SVNRevision .HEAD );
482+ diffClient .doMergeReIntegrate (getBranchUrl (srcBranchName ), SVNRevision .HEAD , wc .getFolder (), false );
483+ try {
484+ // (getBranchUrl(srcBranchName),
485+ // SVNRevision.HEAD, Collections.singleton(range),
486+ // wc.getFolder(), SVNDepth.UNKNOWN, true, false, false, false);
487+
488+
489+
490+ // final List<SVNLogEntry> entries = new ArrayList<>();
491+ // repository.log(new String[] { "branches/" + srcBranchName }, -1 /* start from head descending */,
492+ // 0, true, true, -1, new ISVNLogEntryHandler() {
493+ // @Override
494+ // public void handleLogEntry(SVNLogEntry logEntry) throws SVNException {
495+ // entries.add(logEntry);
496+ // }
497+ // });
498+ // final SVNLogEntry branchFirstCommit = entries.get(entries.size() - 1);
499+ final String wcFolderPath = wc .getFolder ().getPath ();
500+ //
501+ // ðàáîòàåò ïðàâèëüíî, íî NPE
502+ // http://stackoverflow.com/questions/11851584/how-to-list-locally-modified-unversioned-files-using-svnkit
503+ //diffClient.doDiffStatus(wc.getFolder(), SVNRevision.WORKING, getBranchUrl(dstBranchName), SVNRevision.HEAD,
504+ // diffClient.doDiffStatus(getBranchUrl(srcBranchName), SVNRevision.HEAD,
505+ // getBranchUrl(srcBranchName), SVNRevision.create(getBranchFirstCommit(srcBranchName).getRevision()),
506+
507+ // diffClient.doDiffStatus(wc.getFolder(), SVNRevision.WORKING, getBranchUrl(dstBranchName), SVNRevision.HEAD,
508+ // SVNDepth.FILES, true /* useAncestry */, new ISVNDiffStatusHandler() {
509+ //
510+ // @Override
511+ // public void handleDiffStatus(SVNDiffStatus diffStatus) throws SVNException {
512+ //
513+ // //if (diffStatus.getURL().getPath().contains(getBranchUrl(null).getPath())) {
514+ // // return;
515+ // //}
516+ // VCSDiffEntry entry = new VCSDiffEntry(diffStatus.getPath(),
517+ // SVNChangeTypeToVCSChangeType(diffStatus.getModificationType()));
518+ // res.add(entry);
519+ //
520+ // }
521+ //
522+ // private VCSChangeType SVNChangeTypeToVCSChangeType(SVNStatusType modificationType) {
523+ // if (SVNStatusType.STATUS_ADDED.equals(modificationType)) {
524+ // return VCSChangeType.ADD;
525+ // } else if (SVNStatusType.STATUS_DELETED.equals(modificationType)) {
526+ // return VCSChangeType.DELETE;
527+ // } else if (SVNStatusType.STATUS_MODIFIED.equals(modificationType)) {
528+ // return VCSChangeType.MODIFY;
529+ // } else {
530+ // return VCSChangeType.UNKNOWN;
531+ // }
532+ // }
533+ // });
534+
535+ // @Override
536+ // public void handleStatus(SVNStatus status) throws SVNException {
537+ // if (status.getKind() == SVNNodeKind.DIR) {
538+ // return;
539+ // }
540+ // VCSDiffEntry entry = new VCSDiffEntry(status.getFile().getPath().replace(wcFolderPath + "\\", ""),
541+ // status.
542+ // SVNChangeTypeToVCSChangeType(status.getCombinedRemoteNodeAndContentsStatus()));
543+ // res.add(entry);
544+ //
545+ // }
546+ //
547+ // private VCSChangeType SVNChangeTypeToVCSChangeType(SVNStatusType modificationType) {
548+ // if (SVNStatusType.STATUS_ADDED.equals(modificationType)) {
549+ // return VCSChangeType.ADD;
550+ // } else if (SVNStatusType.STATUS_DELETED.equals(modificationType)) {
551+ // return VCSChangeType.DELETE;
552+ // } else if (SVNStatusType.STATUS_MODIFIED.equals(modificationType)) {
553+ // return VCSChangeType.MODIFY;
554+ // } else {
555+ // return VCSChangeType.UNKNOWN;
556+ // }
557+ // }
558+ // });
559+ final List <String > folders = new ArrayList <>();
560+
561+
562+
563+ clientManager .getStatusClient ().doStatus (wc .getFolder (), SVNRevision .BASE , SVNDepth .INFINITY ,
564+ false /* remote */ , false /* reportAll, including normal state */ , false /* includeIgnored */ , true /* obsolete */ ,
565+
566+ // wc.getFolder(), SVNRevision.WORKING, SVNDepth.INFINITY, true, false /* do not include unchanged files */,
567+ // false, false,
568+ new ISVNStatusHandler () {
569+ @ Override
570+ public void handleStatus (SVNStatus status ) throws SVNException {
571+ if (status .getKind () == SVNNodeKind .DIR ) {
572+ folders .add (status .getFile ().getPath ().replace (wcFolderPath + "\\ " , "" ));
573+ return ;
574+ }
575+ VCSDiffEntry entry = new VCSDiffEntry (status .getFile ().getPath ().replace (wcFolderPath + "\\ " , "" ),
576+ SVNChangeTypeToVCSChangeType (status .getCombinedNodeAndContentsStatus ()));
577+ res .add (entry );
578+
579+ }
580+
581+ private VCSChangeType SVNChangeTypeToVCSChangeType (SVNStatusType modificationType ) {
582+ if (SVNStatusType .STATUS_ADDED .equals (modificationType )) {
583+ return VCSChangeType .ADD ;
584+ } else if (SVNStatusType .STATUS_DELETED .equals (modificationType )) {
585+ return VCSChangeType .DELETE ;
586+ } else if (SVNStatusType .STATUS_MODIFIED .equals (modificationType )) {
587+ return VCSChangeType .MODIFY ;
588+ } else {
589+ return VCSChangeType .UNKNOWN ;
590+ }
591+ }
409592
410- return res ;
593+
594+ }, null );
595+
596+
597+ // diffClient.doDiffStatus(wc.getFolder(), SVNRevision.BASE, wc.getFolder(), SVNRevision.WORKING,
598+ // SVNDepth.INFINITY, false, new ISVNDiffStatusHandler() {
599+ //
600+ // @Override
601+ // public void handleDiffStatus(SVNDiffStatus diffStatus) throws SVNException {
602+ // if (diffStatus.getPath().length() == 0 ||
603+ // diffStatus.getKind() == SVNNodeKind.DIR) {
604+ // return;
605+ // }
606+ // VCSDiffEntry entry = new VCSDiffEntry(diffStatus.getPath(),
607+ // SVNChangeTypeToVCSChangeType(diffStatus.getModificationType()));
608+ // res.add(entry);
609+ // }
610+ //
611+ // private VCSChangeType SVNChangeTypeToVCSChangeType(SVNStatusType modificationType) {
612+ // if (SVNStatusType.STATUS_ADDED.equals(modificationType)) {
613+ // return VCSChangeType.ADD;
614+ // } else if (SVNStatusType.STATUS_DELETED.equals(modificationType)) {
615+ // return VCSChangeType.DELETE;
616+ // } else if (SVNStatusType.STATUS_MODIFIED.equals(modificationType)) {
617+ // return VCSChangeType.MODIFY;
618+ // } else {
619+ // return VCSChangeType.UNKNOWN;
620+ // }
621+ // }
622+ // });
623+
624+ return res ;
625+
626+ } finally {
627+ SVNWCClient wcClient = getRevertClient (options );
628+ try {
629+ wcClient .doRevert (new File [] {wc .getFolder ()}, SVNDepth .INFINITY , null );
630+ } catch (Exception e ) {
631+ wc .setCorrupted (true );
632+ }
633+ }
411634 }
412635
413636 @ Override
@@ -474,7 +697,7 @@ private void listEntries(Set<String> entries, String path) throws SVNException {
474697 public List <String > getCommitMessages (String branchName , Integer limit ) {
475698 final List <String > res = new ArrayList <>();
476699 try {
477- repository .log (new String [] { branchName == null ? MASTER_PATH : BRANCHES_PATH + branchName },
700+ repository .log (new String [] { getBranchPath ( branchName ) },
478701 -1 /* start from head descending */ ,
479702 0 , true , true , limit , new ISVNLogEntryHandler () {
480703 @ Override
0 commit comments