From 49472432faf162408b83cfc1581196e48169acec Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 15 Apr 2014 18:43:51 +0400 Subject: [PATCH 01/65] svn: Refactored SvnMergeInfoTest - methods extracted, lots of duplication removed --- .../jetbrains/idea/svn/SvnMergeInfoTest.java | 731 ++++++++---------- .../idea/svn16/SvnMergeInfoTest.java | 1 + 2 files changed, 314 insertions(+), 418 deletions(-) diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java index cfcb5c728b56..bf31172fd2d9 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java @@ -16,14 +16,14 @@ package org.jetbrains.idea.svn; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vcs.CommittedChangesProvider; -import com.intellij.openapi.vcs.ProjectLevelVcsManager; -import com.intellij.openapi.vcs.VcsConfiguration; -import com.intellij.openapi.vcs.VcsTestUtil; +import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl; import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.dialogs.WCInfo; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.history.SvnRepositoryLocation; @@ -33,6 +33,7 @@ import org.jetbrains.idea.svn.mergeinfo.SvnMergeInfoCache; import org.junit.Assert; import org.junit.Test; import org.tmatesoft.svn.core.SVNDepth; +import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNInfo; import org.tmatesoft.svn.core.wc.SVNPropertyData; @@ -40,15 +41,23 @@ import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNWCClient; import java.io.File; +import java.io.IOException; import java.util.List; // TODO: Many tests in this class are written with direct SVNKit usage - could not utilize it for svn 1.8 public class SvnMergeInfoTest extends Svn17TestCase { + + private static final String CONTENT1 = "123\n456\n123"; + private static final String CONTENT2 = "123\n456\n123\n4"; + private File myBranchVcsRoot; private ProjectLevelVcsManagerImpl myProjectLevelVcsManager; private WCInfo myWCInfo; private OneShotMergeInfoHelper myOneShotMergeInfoHelper; + private SvnVcs myVcs; + private BranchInfo myMergeChecker; + @Override public void setUp() throws Exception { super.setUp(); @@ -65,523 +74,409 @@ public class SvnMergeInfoTest extends Svn17TestCase { myWCInfo = new WCInfo(root, true, SVNDepth.INFINITY); myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myProject, myWCInfo, myRepoUrl + "/trunk"); - SvnConfiguration.getInstance(myProject).setCheckNestedForQuickMerge(true); -// AbstractVcs vcsFound = myProjectLevelVcsManager.findVcsByName(SvnVcs.VCS_NAME); -// Assert.assertEquals(1, myProjectLevelVcsManager.getRootsUnderVcs(vcsFound).length); + myVcs = SvnVcs.getInstance(myProject); + myVcs.getSvnConfiguration().setCheckNestedForQuickMerge(true); + // AbstractVcs vcsFound = myProjectLevelVcsManager.findVcsByName(SvnVcs.VCS_NAME); + // Assert.assertEquals(1, myProjectLevelVcsManager.getRootsUnderVcs(vcsFound).length); + + enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); + enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); + + final String repoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString(); + myMergeChecker = new BranchInfo(myVcs, repoUrl, repoUrl + "/branch", repoUrl + "/trunk", repoUrl + "/trunk"); } @Test public void testSimpleNotMerged() throws Exception { - enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); - enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); - - final File trunk = new File(myTempDirFixture.getTempDirPath(), "trunk"); - trunk.mkdir(); - Thread.sleep(100); - final File folder = new File(trunk, "folder"); - folder.mkdir(); - Thread.sleep(100); - final File f1 = new File(folder, "f1.txt"); - f1.createNewFile(); - new File(folder, "f2.txt").createNewFile(); - Thread.sleep(100); + final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); + final File folder = newFolder(trunk, "folder"); + final File f1 = newFile(folder, "f1.txt"); + newFile(folder, "f2.txt"); + waitTime(); - runInAndVerifyIgnoreOutput("import", "-m", "test", trunk.getAbsolutePath(), myRepoUrl + "/trunk"); - runInAndVerifyIgnoreOutput("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch"); - - FileUtil.delete(trunk); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/trunk", trunk.getAbsolutePath()); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/branch", myBranchVcsRoot.getAbsolutePath()); + importAndCheckOut(trunk); // rev 3 - final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f1); - VcsTestUtil.editFileInCommand(myProject, vf, "123\n456\n123"); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", trunk.getAbsolutePath()); + editAndCommit(trunk, f1); - final SvnVcs vcs = SvnVcs.getInstance(myProject); - final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); - final List changeListList = - committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), - new SvnRepositoryLocation(myRepoUrl + "/trunk"), 0); - - final SvnChangeList changeList = changeListList.get(0); - final BranchInfo mergeChecker = - new BranchInfo(vcs, myRepoUrl, myRepoUrl + "/branch", myRepoUrl + "/trunk", myRepoUrl + "/trunk"); - final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath()); - assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result); - - myOneShotMergeInfoHelper.prepare(); - final SvnMergeInfoCache.MergeCheckResult oneShotResult = myOneShotMergeInfoHelper.checkList(changeList); - Assert.assertEquals(SvnMergeInfoCache.MergeCheckResult.NOT_MERGED, oneShotResult); + assertMergeResult(getTrunkChangeLists(), SvnMergeInfoCache.MergeCheckResult.NOT_MERGED); } @Test public void testSimpleMerged() throws Exception { - enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); - enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); + final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); + final File folder = newFolder(trunk, "folder"); + final File f1 = newFile(folder, "f1.txt"); + newFile(folder, "f2.txt"); + waitTime(); - final File trunk = new File(myTempDirFixture.getTempDirPath(), "trunk"); - trunk.mkdir(); - Thread.sleep(100); - final File folder = new File(trunk, "folder"); - folder.mkdir(); - Thread.sleep(100); - final File f1 = new File(folder, "f1.txt"); - f1.createNewFile(); - new File(folder, "f2.txt").createNewFile(); - Thread.sleep(100); - - runInAndVerifyIgnoreOutput("import", "-m", "test", trunk.getAbsolutePath(), myRepoUrl + "/trunk"); - runInAndVerifyIgnoreOutput("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch"); - - FileUtil.delete(trunk); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/trunk", trunk.getAbsolutePath()); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/branch", myBranchVcsRoot.getAbsolutePath()); + importAndCheckOut(trunk); // rev 3 - final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f1); - VcsTestUtil.editFileInCommand(myProject, vf, "123\n456\n123"); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", trunk.getAbsolutePath()); + editAndCommit(trunk, f1); // rev 4: record as merged into branch - runInAndVerifyIgnoreOutput("merge", "-c", "3", myRepoUrl + "/trunk", myBranchVcsRoot.getAbsolutePath(), "--record-only"); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", myBranchVcsRoot.getAbsolutePath()); + recordMerge(myBranchVcsRoot, myRepoUrl + "/trunk", "-c", "3"); + commitFile(myBranchVcsRoot); + updateFile(myBranchVcsRoot); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("up", myBranchVcsRoot.getAbsolutePath()); + assertMergeInfo(myBranchVcsRoot, "/trunk:3"); - final SvnVcs vcs = SvnVcs.getInstance(myProject); - final SVNWCClient wcClient = vcs.createWCClient(); - final SVNPropertyData data = wcClient.doGetProperty(myBranchVcsRoot, "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING); - assert data != null && data.getValue() != null && "/trunk:3".equals(data.getValue().getString()); - - final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); - final List changeListList = - committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), - new SvnRepositoryLocation(myRepoUrl + "/trunk"), 0); - - final SvnChangeList changeList = changeListList.get(0); - final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString(); - final BranchInfo mergeChecker = - new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk"); - final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath()); - assert SvnMergeInfoCache.MergeCheckResult.MERGED.equals(result); - - myOneShotMergeInfoHelper.prepare(); - final SvnMergeInfoCache.MergeCheckResult oneShotResult = myOneShotMergeInfoHelper.checkList(changeList); - Assert.assertEquals(SvnMergeInfoCache.MergeCheckResult.MERGED, oneShotResult); + assertMergeResult(getTrunkChangeLists(), SvnMergeInfoCache.MergeCheckResult.MERGED); } @Test public void testEmptyMergeinfoBlocks() throws Exception { - enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); - enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); + final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); + final File folder = newFolder(trunk, "folder"); + final File f1 = newFile(folder, "f1.txt"); + newFile(folder, "f2.txt"); + waitTime(); - final File trunk = new File(myTempDirFixture.getTempDirPath(), "trunk"); - trunk.mkdir(); - Thread.sleep(100); - final File folder = new File(trunk, "folder"); - folder.mkdir(); - Thread.sleep(100); - final File f1 = new File(folder, "f1.txt"); - f1.createNewFile(); - new File(folder, "f2.txt").createNewFile(); - Thread.sleep(100); - - runInAndVerifyIgnoreOutput("import", "-m", "test", trunk.getAbsolutePath(), myRepoUrl + "/trunk"); - runInAndVerifyIgnoreOutput("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch"); - - FileUtil.delete(trunk); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/trunk", trunk.getAbsolutePath()); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/branch", myBranchVcsRoot.getAbsolutePath()); + importAndCheckOut(trunk); // rev 3 - final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f1); - VcsTestUtil.editFileInCommand(myProject, vf, "123\n456\n123"); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", trunk.getAbsolutePath()); + editAndCommit(trunk, f1); // rev 4: record as merged into branch - runInAndVerifyIgnoreOutput("merge", "-c", "3", myRepoUrl + "/trunk", myBranchVcsRoot.getAbsolutePath()); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", myBranchVcsRoot.getAbsolutePath()); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("up", myBranchVcsRoot.getAbsolutePath()); - Thread.sleep(100); + merge(myBranchVcsRoot, myRepoUrl + "/trunk", "-c", "3"); + commitFile(myBranchVcsRoot); + updateFile(myBranchVcsRoot); // rev5: put blocking empty mergeinfo //runInAndVerifyIgnoreOutput("merge", "-c", "-3", myRepoUrl + "/trunk/folder", new File(myBranchVcsRoot, "folder").getAbsolutePath(), "--record-only")); - runInAndVerifyIgnoreOutput("merge", "-r", "3:2", myRepoUrl + "/trunk/folder", new File(myBranchVcsRoot, "folder").getAbsolutePath()); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", myBranchVcsRoot.getAbsolutePath()); + merge(new File(myBranchVcsRoot, "folder"), myRepoUrl + "/trunk/folder", "-r", "3:2"); + commitFile(myBranchVcsRoot); + updateFile(myBranchVcsRoot); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("up", myBranchVcsRoot.getAbsolutePath()); + assertMergeInfo(myBranchVcsRoot, "/trunk:3"); + assertMergeInfo(new File(myBranchVcsRoot, "folder"), ""); - final SvnVcs vcs = SvnVcs.getInstance(myProject); - final SVNWCClient wcClient = vcs.createWCClient(); - final SVNPropertyData data = wcClient.doGetProperty(myBranchVcsRoot, "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING); - assert data != null && data.getValue() != null && "/trunk:3".equals(data.getValue().getString()); - final SVNPropertyData dataFolder = wcClient.doGetProperty(new File(myBranchVcsRoot, "folder"), "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING); - assert dataFolder != null && dataFolder.getValue() != null && "".equals(dataFolder.getValue().getString()); - - final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); - final List changeListList = - committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), - new SvnRepositoryLocation(myRepoUrl + "/trunk"), 0); - - final SvnChangeList changeList = changeListList.get(0); - final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString(); - final BranchInfo mergeChecker = - new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk"); - final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath()); - assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result); - - myOneShotMergeInfoHelper.prepare(); - final SvnMergeInfoCache.MergeCheckResult oneShotResult = myOneShotMergeInfoHelper.checkList(changeList); - Assert.assertEquals(SvnMergeInfoCache.MergeCheckResult.NOT_MERGED, oneShotResult); // todo + assertMergeResult(getTrunkChangeLists(), SvnMergeInfoCache.MergeCheckResult.NOT_MERGED); } @Test public void testNonInheritableMergeinfo() throws Exception { - enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); - enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); + final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); + final File folder = newFolder(trunk, "folder"); + final File f1 = newFile(folder, "f1.txt"); + newFile(folder, "f2.txt"); + waitTime(); - final File trunk = new File(myTempDirFixture.getTempDirPath(), "trunk"); - trunk.mkdir(); - Thread.sleep(100); - final File folder = new File(trunk, "folder"); - folder.mkdir(); - Thread.sleep(100); - final File f1 = new File(folder, "f1.txt"); - f1.createNewFile(); - new File(folder, "f2.txt").createNewFile(); - Thread.sleep(100); - - runInAndVerifyIgnoreOutput("import", "-m", "test", trunk.getAbsolutePath(), myRepoUrl + "/trunk"); - runInAndVerifyIgnoreOutput("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch"); - - FileUtil.delete(trunk); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/trunk", trunk.getAbsolutePath()); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/branch", myBranchVcsRoot.getAbsolutePath()); + importAndCheckOut(trunk); // rev 3 - final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f1); - VcsTestUtil.editFileInCommand(myProject, vf, "123\n456\n123"); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", trunk.getAbsolutePath()); + editAndCommit(trunk, f1); // rev 4: record non inheritable merge - runInAndVerifyIgnoreOutput("propset", "svn:mergeinfo", "/trunk:3*", myBranchVcsRoot.getAbsolutePath()); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", myBranchVcsRoot.getAbsolutePath()); + setMergeInfo(myBranchVcsRoot, "/trunk:3*"); + commitFile(myBranchVcsRoot); + updateFile(myBranchVcsRoot); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("up", myBranchVcsRoot.getAbsolutePath()); + assertMergeInfo(myBranchVcsRoot, "/trunk:3*"); - final SvnVcs vcs = SvnVcs.getInstance(myProject); - final SVNWCClient wcClient = vcs.createWCClient(); - final SVNPropertyData data = wcClient.doGetProperty(myBranchVcsRoot, "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING); - assert data != null && data.getValue() != null && "/trunk:3*".equals(data.getValue().getString()); - - final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); - final List changeListList = - committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), - new SvnRepositoryLocation(myRepoUrl + "/trunk"), 0); - - final SvnChangeList changeList = changeListList.get(0); - final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString(); - final BranchInfo mergeChecker = - new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk"); - final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath()); - assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result); - - myOneShotMergeInfoHelper.prepare(); - final SvnMergeInfoCache.MergeCheckResult oneShotResult = myOneShotMergeInfoHelper.checkList(changeList); - Assert.assertEquals(SvnMergeInfoCache.MergeCheckResult.NOT_MERGED, oneShotResult); + assertMergeResult(getTrunkChangeLists(), SvnMergeInfoCache.MergeCheckResult.NOT_MERGED); } @Test public void testOnlyImmediateInheritableMergeinfo() throws Exception { - enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); - enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); + final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); + final File folder = newFolder(trunk, "folder"); + final File f1 = newFile(folder, "f1.txt"); + newFile(folder, "f2.txt"); + waitTime(); - final File trunk = new File(myTempDirFixture.getTempDirPath(), "trunk"); - trunk.mkdir(); - Thread.sleep(100); - final File folder = new File(trunk, "folder"); - folder.mkdir(); - Thread.sleep(100); - final File f1 = new File(folder, "f1.txt"); - f1.createNewFile(); - new File(folder, "f2.txt").createNewFile(); - Thread.sleep(100); - - runInAndVerifyIgnoreOutput("import", "-m", "test", trunk.getAbsolutePath(), myRepoUrl + "/trunk"); - runInAndVerifyIgnoreOutput("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch"); - - FileUtil.delete(trunk); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/trunk", trunk.getAbsolutePath()); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/branch", myBranchVcsRoot.getAbsolutePath()); + importAndCheckOut(trunk); // rev 3 - final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f1); - VcsTestUtil.editFileInCommand(myProject, vf, "123\n456\n123"); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", trunk.getAbsolutePath()); - Thread.sleep(100); + editAndCommit(trunk, f1, CONTENT1); // rev4 - VcsTestUtil.editFileInCommand(myProject, vf, "123\n456\n123\n4"); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", trunk.getAbsolutePath()); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("up", myBranchVcsRoot.getAbsolutePath()); - Thread.sleep(100); + editAndCommit(trunk, f1, CONTENT2); + updateFile(myBranchVcsRoot); // rev 4: record non inheritable merge - runInAndVerifyIgnoreOutput("propset", "svn:mergeinfo", "/trunk:3,4", myBranchVcsRoot.getAbsolutePath()); - runInAndVerifyIgnoreOutput("propset", "svn:mergeinfo", "/trunk:3", new File(myBranchVcsRoot, "folder").getAbsolutePath()); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", myBranchVcsRoot.getAbsolutePath()); + setMergeInfo(myBranchVcsRoot, "/trunk:3,4"); + setMergeInfo(new File(myBranchVcsRoot, "folder"), "/trunk:3"); + commitFile(myBranchVcsRoot); + updateFile(myBranchVcsRoot); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("up", myBranchVcsRoot.getAbsolutePath()); + assertMergeInfo(myBranchVcsRoot, "/trunk:3-4", "/trunk:3,4"); + assertMergeInfo(new File(myBranchVcsRoot, "folder"), "/trunk:3"); - final SvnVcs vcs = SvnVcs.getInstance(myProject); - final SVNWCClient wcClient = vcs.createWCClient(); - final SVNPropertyData data = wcClient.doGetProperty(myBranchVcsRoot, "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING); - assert data != null && data.getValue() != null && ("/trunk:3-4".equals(data.getValue().getString()) || - "/trunk:3,4".equals(data.getValue().getString())); - final SVNPropertyData dataFolder = wcClient.doGetProperty(new File(myBranchVcsRoot, "folder"), "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING); - assert dataFolder != null && dataFolder.getValue() != null && "/trunk:3".equals(dataFolder.getValue().getString()); + final List changeListList = getTrunkChangeLists(); - final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); - final List changeListList = - committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), - new SvnRepositoryLocation(myRepoUrl + "/trunk"), 0); - - final SvnChangeList changeList4 = changeListList.get(0); - assert changeList4.getNumber() == 4; - final SvnChangeList changeList3 = changeListList.get(1); - assert changeList3.getNumber() == 3; - - final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString(); - final BranchInfo mergeChecker = - new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk"); - SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList3, myBranchVcsRoot.getAbsolutePath()); - assert SvnMergeInfoCache.MergeCheckResult.MERGED.equals(result); - result = mergeChecker.checkList(changeList4, myBranchVcsRoot.getAbsolutePath()); - assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result); - - myOneShotMergeInfoHelper.prepare(); - final SvnMergeInfoCache.MergeCheckResult oneShotResult = myOneShotMergeInfoHelper.checkList(changeList3); - Assert.assertEquals(SvnMergeInfoCache.MergeCheckResult.MERGED, oneShotResult); - - final SvnMergeInfoCache.MergeCheckResult oneShotResult1 = myOneShotMergeInfoHelper.checkList(changeList4); - Assert.assertEquals(SvnMergeInfoCache.MergeCheckResult.NOT_MERGED, oneShotResult1); + assertRevisions(changeListList, 4, 3); + assertMergeResult(changeListList, SvnMergeInfoCache.MergeCheckResult.NOT_MERGED, SvnMergeInfoCache.MergeCheckResult.MERGED); } @Test public void testTwoPaths() throws Exception { - enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); - enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); + final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); + final File folder = newFolder(trunk, "folder"); + final File f1 = newFile(folder, "f1.txt"); + final File folder1 = newFolder(folder, "folder1"); + final File f2 = newFile(folder1, "f2.txt"); + waitTime(); - final File trunk = new File(myTempDirFixture.getTempDirPath(), "trunk"); - trunk.mkdir(); - Thread.sleep(100); - final File folder = new File(trunk, "folder"); - folder.mkdir(); - Thread.sleep(100); - final File f1 = new File(folder, "f1.txt"); - f1.createNewFile(); - final File folder1 = new File(folder, "folder1"); - folder1.mkdir(); - final File f2 = new File(folder1, "f2.txt"); - f2.createNewFile(); - Thread.sleep(100); - - runInAndVerifyIgnoreOutput("import", "-m", "test", trunk.getAbsolutePath(), myRepoUrl + "/trunk"); - runInAndVerifyIgnoreOutput("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch"); - - FileUtil.delete(trunk); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/trunk", trunk.getAbsolutePath()); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/branch", myBranchVcsRoot.getAbsolutePath()); + importAndCheckOut(trunk); // rev 3 - final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f1); - VcsTestUtil.editFileInCommand(myProject, vf, "123\n456\n123"); - final VirtualFile vf2 = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f2); - VcsTestUtil.editFileInCommand(myProject, vf2, "123\n456\n123"); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", trunk.getAbsolutePath()); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("up", myBranchVcsRoot.getAbsolutePath()); - Thread.sleep(100); + editFile(f1); + editFile(f2); + commitFile(trunk); + updateFile(myBranchVcsRoot); // rev 4: record non inheritable merge - runInAndVerifyIgnoreOutput("propset", "svn:mergeinfo", "/trunk:3", myBranchVcsRoot.getAbsolutePath()); + setMergeInfo(myBranchVcsRoot, "/trunk:3"); // this makes not merged for f2 path - runInAndVerifyIgnoreOutput("propset", "svn:mergeinfo", "/trunk:3*", new File(myBranchVcsRoot, "folder/folder1").getAbsolutePath()); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", myBranchVcsRoot.getAbsolutePath()); + setMergeInfo(new File(myBranchVcsRoot, "folder/folder1"), "/trunk:3*"); + commitFile(myBranchVcsRoot); + updateFile(myBranchVcsRoot); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("up", myBranchVcsRoot.getAbsolutePath()); + assertMergeInfo(myBranchVcsRoot, "/trunk:3"); + assertMergeInfo(new File(myBranchVcsRoot, "folder/folder1"), "/trunk:3*"); - final SvnVcs vcs = SvnVcs.getInstance(myProject); - final SVNWCClient wcClient = vcs.createWCClient(); - final SVNPropertyData data = wcClient.doGetProperty(myBranchVcsRoot, "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING); - assert data != null && data.getValue() != null && "/trunk:3".equals(data.getValue().getString()); - final SVNPropertyData dataFolder = wcClient.doGetProperty(new File(myBranchVcsRoot, "folder/folder1"), "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING); - assert dataFolder != null && dataFolder.getValue() != null && "/trunk:3*".equals(dataFolder.getValue().getString()); + final List changeListList = getTrunkChangeLists(); - final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); - final List changeListList = - committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), - new SvnRepositoryLocation(myRepoUrl + "/trunk"), 0); - - final SvnChangeList changeList3 = changeListList.get(0); - assert changeList3.getNumber() == 3; - - final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString(); - final BranchInfo mergeChecker = - new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk"); - SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList3, myBranchVcsRoot.getAbsolutePath()); - assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result); - - myOneShotMergeInfoHelper.prepare(); - final SvnMergeInfoCache.MergeCheckResult oneShotResult = myOneShotMergeInfoHelper.checkList(changeList3); - Assert.assertEquals(SvnMergeInfoCache.MergeCheckResult.NOT_MERGED, oneShotResult); + assertRevisions(changeListList, 3); + assertMergeResult(changeListList, SvnMergeInfoCache.MergeCheckResult.NOT_MERGED); } @Test public void testWhenInfoInRepo() throws Exception { - enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); - enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); + final File fullBranch = newFolder(myTempDirFixture.getTempDirPath(), "fullBranch"); - final File fullBranch = new File(myTempDirFixture.getTempDirPath(), "fullBranch"); - fullBranch.mkdir(); - - final File trunk = new File(myTempDirFixture.getTempDirPath(), "trunk"); - trunk.mkdir(); - Thread.sleep(100); - final File folder = new File(trunk, "folder"); - folder.mkdir(); - Thread.sleep(100); - final File f1 = new File(folder, "f1.txt"); - f1.createNewFile(); + final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); + final File folder = newFolder(trunk, "folder"); + final File f1 = newFile(folder, "f1.txt"); // this will be taken as branch wc root - final File folder1 = new File(folder, "folder1"); - folder1.mkdir(); - final File f2 = new File(folder1, "f2.txt"); - f2.createNewFile(); - Thread.sleep(100); + final File folder1 = newFolder(folder, "folder1"); + final File f2 = newFile(folder1, "f2.txt"); + waitTime(); - runInAndVerifyIgnoreOutput("import", "-m", "test", trunk.getAbsolutePath(), myRepoUrl + "/trunk"); - runInAndVerifyIgnoreOutput("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch"); - - FileUtil.delete(trunk); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/trunk", trunk.getAbsolutePath()); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/branch", fullBranch.getAbsolutePath()); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/branch/folder/folder1", myBranchVcsRoot.getAbsolutePath()); + importAndCheckOut(trunk, fullBranch); + checkOutFile(myRepoUrl + "/branch/folder/folder1", myBranchVcsRoot); // rev 3 : f2 changed - final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f2); - VcsTestUtil.editFileInCommand(myProject, vf, "123\n456\n123"); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", trunk.getAbsolutePath()); + editAndCommit(trunk, f2); // rev 4: record as merged into branch using full branch WC - runInAndVerifyIgnoreOutput("merge", "-c", "3", myRepoUrl + "/trunk", fullBranch.getAbsolutePath(), "--record-only"); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", fullBranch.getAbsolutePath()); + recordMerge(fullBranch, myRepoUrl + "/trunk", "-c", "3"); + commitFile(fullBranch); + updateFile(myBranchVcsRoot); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("up", myBranchVcsRoot.getAbsolutePath()); + final List changeListList = getTrunkChangeLists(); - final SvnVcs vcs = SvnVcs.getInstance(myProject); - - final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); - final List changeListList = - committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), - new SvnRepositoryLocation(myRepoUrl + "/trunk"), 0); - - final SvnChangeList changeList3 = changeListList.get(0); - assert changeList3.getNumber() == 3; - - final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString(); - final BranchInfo mergeChecker = - new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk"); - SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList3, myBranchVcsRoot.getAbsolutePath()); - assert SvnMergeInfoCache.MergeCheckResult.MERGED.equals(result); + assertRevisions(changeListList, 3); + assertMergeResult(changeListList.get(0), SvnMergeInfoCache.MergeCheckResult.MERGED); } @Test public void testMixedWorkingRevisions() throws Exception { - enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); - enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); + final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); + final File folder = newFolder(trunk, "folder"); + final File f1 = newFile(folder, "f1.txt"); + newFile(folder, "f2.txt"); + waitTime(); - final File trunk = new File(myTempDirFixture.getTempDirPath(), "trunk"); - trunk.mkdir(); - Thread.sleep(100); - final File folder = new File(trunk, "folder"); - folder.mkdir(); - Thread.sleep(100); - final File f1 = new File(folder, "f1.txt"); - f1.createNewFile(); - new File(folder, "f2.txt").createNewFile(); - Thread.sleep(100); + importAndCheckOut(trunk); + // rev 3 + editAndCommit(trunk, f1); + + // rev 4: record non inheritable merge + setMergeInfo(myBranchVcsRoot, "/trunk:3"); + commitFile(myBranchVcsRoot); + // ! no update! + + assertMergeInfo(myBranchVcsRoot, "/trunk:3"); + + final SVNInfo f1info = myVcs.getInfo(new File(myBranchVcsRoot, "folder/f1.txt")); + assert f1info.getRevision().getNumber() == 2; + + final List changeListList = getTrunkChangeLists(); + final SvnChangeList changeList = changeListList.get(0); + + assertMergeResult(changeList, SvnMergeInfoCache.MergeCheckResult.NOT_MERGED); + + // and after update + updateFile(myBranchVcsRoot); + myMergeChecker.clear(); + + assertMergeResult(changeList, SvnMergeInfoCache.MergeCheckResult.MERGED); + } + + @NotNull + private List getTrunkChangeLists() throws com.intellij.openapi.vcs.VcsException { + final CommittedChangesProvider provider = myVcs.getCommittedChangesProvider(); + + return provider.getCommittedChanges(provider.createDefaultSettings(), new SvnRepositoryLocation(myRepoUrl + "/trunk"), 0); + } + + private void importAndCheckOut(@NotNull File trunk) throws IOException { + importAndCheckOut(trunk, myBranchVcsRoot); + } + + private void importAndCheckOut(@NotNull File trunk, @NotNull File branch) throws IOException { runInAndVerifyIgnoreOutput("import", "-m", "test", trunk.getAbsolutePath(), myRepoUrl + "/trunk"); runInAndVerifyIgnoreOutput("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch"); FileUtil.delete(trunk); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/trunk", trunk.getAbsolutePath()); - runInAndVerifyIgnoreOutput("co", myRepoUrl + "/branch", myBranchVcsRoot.getAbsolutePath()); + checkOutFile(myRepoUrl + "/trunk", trunk); + checkOutFile(myRepoUrl + "/branch", branch); + } - // rev 3 - final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f1); - VcsTestUtil.editFileInCommand(myProject, vf, "123\n456\n123"); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", trunk.getAbsolutePath()); + @NotNull + private VirtualFile editAndCommit(@NotNull File trunk, @NotNull File file) throws InterruptedException, IOException { + return editAndCommit(trunk, file, CONTENT1); + } - // rev 4: record non inheritable merge - runInAndVerifyIgnoreOutput("propset", "svn:mergeinfo", "/trunk:3", myBranchVcsRoot.getAbsolutePath()); - Thread.sleep(100); - runInAndVerifyIgnoreOutput("ci", "-m", "test", myBranchVcsRoot.getAbsolutePath()); + @NotNull + private VirtualFile editAndCommit(@NotNull File trunk, @NotNull File file, @NotNull String content) + throws InterruptedException, IOException { + final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); - Thread.sleep(100); - // ! no update! + return editAndCommit(trunk, vf, content); + } + @NotNull + private VirtualFile editAndCommit(@NotNull File trunk, @NotNull VirtualFile file) throws InterruptedException, IOException { + return editAndCommit(trunk, file, CONTENT1); + } + + @NotNull + private VirtualFile editAndCommit(@NotNull File trunk, @NotNull VirtualFile file, @NotNull String content) + throws InterruptedException, IOException { + editFile(file, content); + commitFile(trunk); + + return file; + } + + private void editFile(@NotNull File file) throws InterruptedException { + editFile(file, CONTENT1); + } + + private void editFile(@NotNull File file, @NotNull String content) throws InterruptedException { + final VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file); + + editFile(vf, content); + } + + private void editFile(@NotNull VirtualFile file, @NotNull String content) throws InterruptedException { + VcsTestUtil.editFileInCommand(myProject, file, content); + waitTime(); + } + + private void assertMergeInfo(@NotNull File file, @NotNull String... values) throws SVNException { + // TODO: Replace with ClientFactory model final SvnVcs vcs = SvnVcs.getInstance(myProject); final SVNWCClient wcClient = vcs.createWCClient(); - final SVNPropertyData data = wcClient.doGetProperty(myBranchVcsRoot, "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING); - assert data != null && data.getValue() != null && "/trunk:3".equals(data.getValue().getString()); + final SVNPropertyData data = wcClient.doGetProperty(file, "svn:mergeinfo", SVNRevision.UNDEFINED, SVNRevision.WORKING); + assert data != null && data.getValue() != null; - final SVNInfo f1info = wcClient.doInfo(new File(myBranchVcsRoot, "folder/f1.txt"), SVNRevision.UNDEFINED); - assert f1info.getRevision().getNumber() == 2; + boolean result = false; - final CommittedChangesProvider committedChangesProvider = vcs.getCommittedChangesProvider(); - final List changeListList = - committedChangesProvider.getCommittedChanges(committedChangesProvider.createDefaultSettings(), - new SvnRepositoryLocation(myRepoUrl + "/trunk"), 0); + for (String value : values) { + result |= value.equals(data.getValue().getString()); + } - final SvnChangeList changeList = changeListList.get(0); - final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString(); - final BranchInfo mergeChecker = - new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk"); - SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath()); - assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result); + assert result; + } - // and after update - runInAndVerifyIgnoreOutput("up", myBranchVcsRoot.getAbsolutePath()); + private void assertMergeResult(@NotNull List changeLists, @NotNull SvnMergeInfoCache.MergeCheckResult... mergeResults) + throws VcsException { + myOneShotMergeInfoHelper.prepare(); + + for (int i = 0; i < mergeResults.length; i++) { + SvnChangeList changeList = changeLists.get(i); + + assertMergeResult(changeList, mergeResults[i]); + assertMergeResultOneShot(changeList, mergeResults[i]); + } + } + + private void assertMergeResult(@NotNull SvnChangeList changeList, @NotNull SvnMergeInfoCache.MergeCheckResult mergeResult) { + assert mergeResult.equals(myMergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath())); + } + + private void assertMergeResultOneShot(@NotNull SvnChangeList changeList, @NotNull SvnMergeInfoCache.MergeCheckResult mergeResult) { + Assert.assertEquals(mergeResult, myOneShotMergeInfoHelper.checkList(changeList)); + } + + private void assertRevisions(@NotNull List changeLists, @NotNull int... revisions) { + for (int i = 0; i < revisions.length; i++) { + assert changeLists.get(i).getNumber() == revisions[i]; + } + } + + private void commitFile(@NotNull File file) throws IOException, InterruptedException { + runInAndVerifyIgnoreOutput("ci", "-m", "test", file.getAbsolutePath()); + waitTime(); + } + + private void updateFile(@NotNull File file) throws IOException, InterruptedException { + runInAndVerifyIgnoreOutput("up", file.getAbsolutePath()); + waitTime(); + } + + private void checkOutFile(@NotNull String url, @NotNull File directory) throws IOException { + runInAndVerifyIgnoreOutput("co", url, directory.getAbsolutePath()); + } + + private void setMergeInfo(@NotNull File file, @NotNull String value) throws IOException, InterruptedException { + runInAndVerifyIgnoreOutput("propset", "svn:mergeinfo", value, file.getAbsolutePath()); + waitTime(); + } + + private void merge(@NotNull File file, @NotNull String url, @NotNull String... revisions) throws IOException, InterruptedException { + merge(file, url, false, revisions); + } + + private void recordMerge(@NotNull File file, @NotNull String url, @NotNull String... revisions) throws IOException, InterruptedException { + merge(file, url, true, revisions); + } + + private void merge(@NotNull File file, @NotNull String url, boolean recordOnly, @NotNull String... revisions) + throws IOException, InterruptedException { + List parameters = ContainerUtil.newArrayList(); + + parameters.add("merge"); + ContainerUtil.addAll(parameters, revisions); + parameters.add(url); + parameters.add(file.getAbsolutePath()); + if (recordOnly) { + parameters.add("--record-only"); + } + + runInAndVerifyIgnoreOutput(ArrayUtil.toObjectArray(parameters, String.class)); + waitTime(); + } + + @NotNull + private static File newFile(File parent, String name) throws IOException { + final File f1 = new File(parent, name); + f1.createNewFile(); + return f1; + } + + @NotNull + private static File newFolder(String parent, String name) throws InterruptedException { + final File trunk = new File(parent, name); + trunk.mkdir(); + waitTime(); + return trunk; + } + + @NotNull + private static File newFolder(File parent, String name) throws InterruptedException { + final File trunk = new File(parent, name); + trunk.mkdir(); + waitTime(); + return trunk; + } + + private static void waitTime() throws InterruptedException { Thread.sleep(100); - - mergeChecker.clear(); - result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath()); - assert SvnMergeInfoCache.MergeCheckResult.MERGED.equals(result); } } diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java index e4928ef30199..73d273135e94 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java @@ -43,6 +43,7 @@ import org.tmatesoft.svn.core.wc.SVNWCClient; import java.io.File; import java.util.List; +// TODO: Full duplicate of SvnMergeInfoTest in org.jetbrains.idea.svn (before latter was refactored). public class SvnMergeInfoTest extends Svn16TestCase { private File myBranchVcsRoot; private ProjectLevelVcsManagerImpl myProjectLevelVcsManager; From 9d618f1d49213ab6279a9a95de59b7cf8418b8e1 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 15 Apr 2014 21:57:00 +0400 Subject: [PATCH 02/65] svn: Refactored SvnMergeInfoTest - methods extracted, duplication removed, warning fixes --- .../jetbrains/idea/svn/SvnMergeInfoTest.java | 138 ++++++++---------- 1 file changed, 57 insertions(+), 81 deletions(-) diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java index bf31172fd2d9..4ecc1cbdd25e 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java @@ -58,10 +58,22 @@ public class SvnMergeInfoTest extends Svn17TestCase { private SvnVcs myVcs; private BranchInfo myMergeChecker; + private File trunk; + private File folder; + private File folder1; + private File f1; + private File f2; + + private String myTrunkUrl; + private String myBranchUrl; + @Override public void setUp() throws Exception { super.setUp(); + myTrunkUrl = myRepoUrl + "/trunk"; + myBranchUrl = myRepoUrl + "/branch"; + myBranchVcsRoot = new File(myTempDirFixture.getTempDirPath(), "branch"); myBranchVcsRoot.mkdir(); @@ -69,15 +81,13 @@ public class SvnMergeInfoTest extends Svn17TestCase { myProjectLevelVcsManager.setDirectoryMapping(myBranchVcsRoot.getAbsolutePath(), SvnVcs.VCS_NAME); VirtualFile vcsRoot = LocalFileSystem.getInstance().findFileByIoFile(myBranchVcsRoot); - Node node = new Node(vcsRoot, SVNURL.parseURIEncoded(myRepoUrl + "/branch"), SVNURL.parseURIEncoded(myRepoUrl)); + Node node = new Node(vcsRoot, SVNURL.parseURIEncoded(myBranchUrl), SVNURL.parseURIEncoded(myRepoUrl)); RootUrlInfo root = new RootUrlInfo(node, WorkingCopyFormat.ONE_DOT_SIX, vcsRoot, null); myWCInfo = new WCInfo(root, true, SVNDepth.INFINITY); - myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myProject, myWCInfo, myRepoUrl + "/trunk"); + myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myProject, myWCInfo, myTrunkUrl); myVcs = SvnVcs.getInstance(myProject); myVcs.getSvnConfiguration().setCheckNestedForQuickMerge(true); - // AbstractVcs vcsFound = myProjectLevelVcsManager.findVcsByName(SvnVcs.VCS_NAME); - // Assert.assertEquals(1, myProjectLevelVcsManager.getRootsUnderVcs(vcsFound).length); enableSilentOperation(VcsConfiguration.StandardConfirmation.ADD); enableSilentOperation(VcsConfiguration.StandardConfirmation.REMOVE); @@ -88,16 +98,9 @@ public class SvnMergeInfoTest extends Svn17TestCase { @Test public void testSimpleNotMerged() throws Exception { - final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); - final File folder = newFolder(trunk, "folder"); - final File f1 = newFile(folder, "f1.txt"); - newFile(folder, "f2.txt"); - waitTime(); - - importAndCheckOut(trunk); + createOneFolderStructure(); // rev 3 - editAndCommit(trunk, f1); assertMergeResult(getTrunkChangeLists(), SvnMergeInfoCache.MergeCheckResult.NOT_MERGED); @@ -105,47 +108,34 @@ public class SvnMergeInfoTest extends Svn17TestCase { @Test public void testSimpleMerged() throws Exception { - final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); - final File folder = newFolder(trunk, "folder"); - final File f1 = newFile(folder, "f1.txt"); - newFile(folder, "f2.txt"); - waitTime(); - - importAndCheckOut(trunk); + createOneFolderStructure(); // rev 3 editAndCommit(trunk, f1); // rev 4: record as merged into branch - recordMerge(myBranchVcsRoot, myRepoUrl + "/trunk", "-c", "3"); + recordMerge(myBranchVcsRoot, myTrunkUrl, "-c", "3"); commitFile(myBranchVcsRoot); updateFile(myBranchVcsRoot); assertMergeInfo(myBranchVcsRoot, "/trunk:3"); - assertMergeResult(getTrunkChangeLists(), SvnMergeInfoCache.MergeCheckResult.MERGED); } @Test public void testEmptyMergeinfoBlocks() throws Exception { - final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); - final File folder = newFolder(trunk, "folder"); - final File f1 = newFile(folder, "f1.txt"); - newFile(folder, "f2.txt"); - waitTime(); - - importAndCheckOut(trunk); + createOneFolderStructure(); // rev 3 editAndCommit(trunk, f1); // rev 4: record as merged into branch - merge(myBranchVcsRoot, myRepoUrl + "/trunk", "-c", "3"); + merge(myBranchVcsRoot, myTrunkUrl, "-c", "3"); commitFile(myBranchVcsRoot); updateFile(myBranchVcsRoot); // rev5: put blocking empty mergeinfo //runInAndVerifyIgnoreOutput("merge", "-c", "-3", myRepoUrl + "/trunk/folder", new File(myBranchVcsRoot, "folder").getAbsolutePath(), "--record-only")); - merge(new File(myBranchVcsRoot, "folder"), myRepoUrl + "/trunk/folder", "-r", "3:2"); + merge(new File(myBranchVcsRoot, "folder"), myTrunkUrl + "/folder", "-r", "3:2"); commitFile(myBranchVcsRoot); updateFile(myBranchVcsRoot); @@ -157,13 +147,7 @@ public class SvnMergeInfoTest extends Svn17TestCase { @Test public void testNonInheritableMergeinfo() throws Exception { - final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); - final File folder = newFolder(trunk, "folder"); - final File f1 = newFile(folder, "f1.txt"); - newFile(folder, "f2.txt"); - waitTime(); - - importAndCheckOut(trunk); + createOneFolderStructure(); // rev 3 editAndCommit(trunk, f1); @@ -180,18 +164,13 @@ public class SvnMergeInfoTest extends Svn17TestCase { @Test public void testOnlyImmediateInheritableMergeinfo() throws Exception { - final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); - final File folder = newFolder(trunk, "folder"); - final File f1 = newFile(folder, "f1.txt"); - newFile(folder, "f2.txt"); - waitTime(); - - importAndCheckOut(trunk); + createOneFolderStructure(); // rev 3 editAndCommit(trunk, f1, CONTENT1); // rev4 editAndCommit(trunk, f1, CONTENT2); + updateFile(myBranchVcsRoot); // rev 4: record non inheritable merge @@ -211,19 +190,13 @@ public class SvnMergeInfoTest extends Svn17TestCase { @Test public void testTwoPaths() throws Exception { - final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); - final File folder = newFolder(trunk, "folder"); - final File f1 = newFile(folder, "f1.txt"); - final File folder1 = newFolder(folder, "folder1"); - final File f2 = newFile(folder1, "f2.txt"); - waitTime(); - - importAndCheckOut(trunk); + createTwoFolderStructure(myBranchVcsRoot); // rev 3 editFile(f1); editFile(f2); commitFile(trunk); + updateFile(myBranchVcsRoot); // rev 4: record non inheritable merge @@ -246,22 +219,15 @@ public class SvnMergeInfoTest extends Svn17TestCase { public void testWhenInfoInRepo() throws Exception { final File fullBranch = newFolder(myTempDirFixture.getTempDirPath(), "fullBranch"); - final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); - final File folder = newFolder(trunk, "folder"); - final File f1 = newFile(folder, "f1.txt"); - // this will be taken as branch wc root - final File folder1 = newFolder(folder, "folder1"); - final File f2 = newFile(folder1, "f2.txt"); - waitTime(); - - importAndCheckOut(trunk, fullBranch); - checkOutFile(myRepoUrl + "/branch/folder/folder1", myBranchVcsRoot); + createTwoFolderStructure(fullBranch); + // folder1 will be taken as branch wc root + checkOutFile(myBranchUrl + "/folder/folder1", myBranchVcsRoot); // rev 3 : f2 changed editAndCommit(trunk, f2); // rev 4: record as merged into branch using full branch WC - recordMerge(fullBranch, myRepoUrl + "/trunk", "-c", "3"); + recordMerge(fullBranch, myTrunkUrl, "-c", "3"); commitFile(fullBranch); updateFile(myBranchVcsRoot); @@ -273,13 +239,7 @@ public class SvnMergeInfoTest extends Svn17TestCase { @Test public void testMixedWorkingRevisions() throws Exception { - final File trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); - final File folder = newFolder(trunk, "folder"); - final File f1 = newFile(folder, "f1.txt"); - newFile(folder, "f2.txt"); - waitTime(); - - importAndCheckOut(trunk); + createOneFolderStructure(); // rev 3 editAndCommit(trunk, f1); @@ -306,11 +266,32 @@ public class SvnMergeInfoTest extends Svn17TestCase { assertMergeResult(changeList, SvnMergeInfoCache.MergeCheckResult.MERGED); } + private void createOneFolderStructure() throws InterruptedException, IOException { + trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); + folder = newFolder(trunk, "folder"); + f1 = newFile(folder, "f1.txt"); + f2 = newFile(folder, "f2.txt"); + waitTime(); + + importAndCheckOut(trunk); + } + + private void createTwoFolderStructure(File branchFolder) throws InterruptedException, IOException { + trunk = newFolder(myTempDirFixture.getTempDirPath(), "trunk"); + folder = newFolder(trunk, "folder"); + f1 = newFile(folder, "f1.txt"); + folder1 = newFolder(folder, "folder1"); + f2 = newFile(folder1, "f2.txt"); + waitTime(); + + importAndCheckOut(trunk, branchFolder); + } + @NotNull private List getTrunkChangeLists() throws com.intellij.openapi.vcs.VcsException { final CommittedChangesProvider provider = myVcs.getCommittedChangesProvider(); - return provider.getCommittedChanges(provider.createDefaultSettings(), new SvnRepositoryLocation(myRepoUrl + "/trunk"), 0); + return provider.getCommittedChanges(provider.createDefaultSettings(), new SvnRepositoryLocation(myTrunkUrl), 0); } private void importAndCheckOut(@NotNull File trunk) throws IOException { @@ -318,12 +299,12 @@ public class SvnMergeInfoTest extends Svn17TestCase { } private void importAndCheckOut(@NotNull File trunk, @NotNull File branch) throws IOException { - runInAndVerifyIgnoreOutput("import", "-m", "test", trunk.getAbsolutePath(), myRepoUrl + "/trunk"); - runInAndVerifyIgnoreOutput("copy", "-m", "test", myRepoUrl + "/trunk", myRepoUrl + "/branch"); + runInAndVerifyIgnoreOutput("import", "-m", "test", trunk.getAbsolutePath(), myTrunkUrl); + runInAndVerifyIgnoreOutput("copy", "-m", "test", myTrunkUrl, myBranchUrl); FileUtil.delete(trunk); - checkOutFile(myRepoUrl + "/trunk", trunk); - checkOutFile(myRepoUrl + "/branch", branch); + checkOutFile(myTrunkUrl, trunk); + checkOutFile(myBranchUrl, branch); } @NotNull @@ -339,11 +320,6 @@ public class SvnMergeInfoTest extends Svn17TestCase { return editAndCommit(trunk, vf, content); } - @NotNull - private VirtualFile editAndCommit(@NotNull File trunk, @NotNull VirtualFile file) throws InterruptedException, IOException { - return editAndCommit(trunk, file, CONTENT1); - } - @NotNull private VirtualFile editAndCommit(@NotNull File trunk, @NotNull VirtualFile file, @NotNull String content) throws InterruptedException, IOException { @@ -404,7 +380,7 @@ public class SvnMergeInfoTest extends Svn17TestCase { Assert.assertEquals(mergeResult, myOneShotMergeInfoHelper.checkList(changeList)); } - private void assertRevisions(@NotNull List changeLists, @NotNull int... revisions) { + private static void assertRevisions(@NotNull List changeLists, @NotNull int... revisions) { for (int i = 0; i < revisions.length; i++) { assert changeLists.get(i).getNumber() == revisions[i]; } From aa5e3fd30c25e44423af345d0f7d7b0a95a0d40f Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 15 Apr 2014 22:03:40 +0400 Subject: [PATCH 03/65] svn: Refactored MergerFactory - removed unused methods --- .../idea/svn/actions/ChangeListsMergerFactory.java | 8 -------- .../idea/svn/actions/ChangeSetMergerFactory.java | 9 --------- .../src/org/jetbrains/idea/svn/dialogs/QuickMerge.java | 7 ------- .../org/jetbrains/idea/svn/integrate/MergerFactory.java | 6 ------ 4 files changed, 30 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ChangeListsMergerFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ChangeListsMergerFactory.java index 38c77bf0dbf0..eac55c666ed2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ChangeListsMergerFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ChangeListsMergerFactory.java @@ -41,12 +41,4 @@ public class ChangeListsMergerFactory implements MergerFactory { String branchName) { return new Merger(vcs, myChangeListsList, target, handler, currentBranchUrl, branchName); } - - public List getListsToMerge() { - return myChangeListsList; - } - - public boolean isMergeAll() { - return false; - } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ChangeSetMergerFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ChangeSetMergerFactory.java index 974035e4ce73..623816513537 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ChangeSetMergerFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ChangeSetMergerFactory.java @@ -26,7 +26,6 @@ import org.tmatesoft.svn.core.SVNURL; import java.io.File; import java.util.ArrayList; -import java.util.Collections; import java.util.List; public class ChangeSetMergerFactory implements MergerFactory { @@ -45,12 +44,4 @@ public class ChangeSetMergerFactory implements MergerFactory { String branchName) { return new PointMerger(vcs, mySelectedList, target, handler, currentBranchUrl, mySelectedChanges, branchName); } - - public List getListsToMerge() { - return Collections.singletonList(mySelectedList); - } - - public boolean isMergeAll() { - return false; - } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java index 230a057f6800..a2dee9f2088a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java @@ -404,13 +404,6 @@ public class QuickMerge { return new BranchMerger(vcs, currentBranchUrl, myWcInfo.getUrl(), myWcInfo.getPath(), handler, reintegrate, myBranchName, reintegrate ? invertor.getWrapped().getTargetRevision() : invertor.getWrapped().getSourceRevision()); } - @Nullable - public List getListsToMerge() { - return null; - } - public boolean isMergeAll() { - return true; - } }; } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergerFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergerFactory.java index 42bb70bf514c..50f881e7dce0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergerFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergerFactory.java @@ -15,14 +15,11 @@ */ package org.jetbrains.idea.svn.integrate; -import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; -import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.update.UpdateEventHandler; import org.tmatesoft.svn.core.SVNURL; import java.io.File; -import java.util.List; public interface MergerFactory { IMerger createMerger(final SvnVcs vcs, @@ -30,7 +27,4 @@ public interface MergerFactory { final UpdateEventHandler handler, final SVNURL currentBranchUrl, String branchName); - boolean isMergeAll(); - @Nullable - List getListsToMerge(); } From 0b9815c08ddb950d81ba9e86af402db302cc8b28 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 15 Apr 2014 22:32:14 +0400 Subject: [PATCH 04/65] svn: Refactored SvnBranchPointsCalculator.WrapperInvertor - explicitly use SvnBranchPointsCalculator.BranchCopyData type (instead of being generic) --- .../idea/svn/dialogs/QuickMerge.java | 34 +++++++-------- .../dialogs/SvnBranchPointsCalculator.java | 42 +++++++++---------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java index a2dee9f2088a..f081229a868b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java @@ -255,7 +255,7 @@ public class QuickMerge { final SvnBranchPointsCalculator.BranchCopyData copyData = new SvnBranchPointsCalculator.BranchCopyData(myWcInfo.getUrl().toString(), -1, mySourceUrl, -1); context.next(new LocalChangesPrompt(false, lists, - new SvnBranchPointsCalculator.WrapperInvertor(false, copyData)), + new SvnBranchPointsCalculator.WrapperInvertor(false, copyData)), new MergeTask(factory, myTitle)); } else { context.cancelEverything(); @@ -353,24 +353,24 @@ public class QuickMerge { queue.add(mergeAllExecutor); } - private class MergeAllWithBranchCopyPoint extends TaskDescriptor implements Consumer, SVNException>> { - private final AtomicReference, SVNException>> myData; + private class MergeAllWithBranchCopyPoint extends TaskDescriptor implements Consumer> { + private final AtomicReference> myData; private MergeAllWithBranchCopyPoint() { super("merge all", Where.AWT); - myData = new AtomicReference, SVNException>>(); + myData = new AtomicReference>(); } @Override - public void consume(TransparentlyFailedValueI, SVNException> value) { + public void consume(TransparentlyFailedValueI value) { myData.set(value); } @Override public void run(ContinuationContext context) { - SvnBranchPointsCalculator.WrapperInvertor invertor; + SvnBranchPointsCalculator.WrapperInvertor invertor; try { - final TransparentlyFailedValueI, SVNException> + final TransparentlyFailedValueI transparentlyFailedValueI = myData.get(); if (transparentlyFailedValueI == null) { finishWithError(context, "Merge start wasn't found", true); @@ -398,7 +398,7 @@ public class QuickMerge { } private MergerFactory createBranchMergerFactory(final boolean reintegrate, - final SvnBranchPointsCalculator.WrapperInvertor invertor) { + final SvnBranchPointsCalculator.WrapperInvertor invertor) { return new MergerFactory() { public IMerger createMerger(SvnVcs vcs, File target, UpdateEventHandler handler, SVNURL currentBranchUrl, String branchName) { return new BranchMerger(vcs, currentBranchUrl, myWcInfo.getUrl(), myWcInfo.getPath(), handler, reintegrate, myBranchName, @@ -532,13 +532,13 @@ public class QuickMerge { } private class MergeCalculator extends TaskDescriptor implements - Consumer, SVNException>> { + Consumer> { private final static String ourOneShotStrategy = "svn.quickmerge.oneShotStrategy"; private final WCInfo myWcInfo; private final String mySourceUrl; private final String myBranchName; private final - AtomicReference, SVNException>> + AtomicReference> myCopyData; private boolean myIsReintegrate; @@ -547,7 +547,7 @@ public class QuickMerge { private final MergeChecker myMergeChecker; @Override - public void consume(TransparentlyFailedValueI, SVNException> value) { + public void consume(TransparentlyFailedValueI value) { myCopyData.set(value); } @@ -566,13 +566,13 @@ public class QuickMerge { myWcInfo.getRootUrl(), mySourceUrl, mySourceUrl, myVcs.createWCClient())); }*/ - myCopyData = new AtomicReference, SVNException>>(); + myCopyData = new AtomicReference>(); } //"Calculating not merged revisions" @Override public void run(ContinuationContext context) { - SvnBranchPointsCalculator.WrapperInvertor copyDataValue = null; + SvnBranchPointsCalculator.WrapperInvertor copyDataValue = null; try { copyDataValue = myCopyData.get().get(); } @@ -642,9 +642,9 @@ public class QuickMerge { } private class ShowRevisionSelector extends TaskDescriptor { - private final SvnBranchPointsCalculator.WrapperInvertor myCopyPoint; + private final SvnBranchPointsCalculator.WrapperInvertor myCopyPoint; - private ShowRevisionSelector(SvnBranchPointsCalculator.WrapperInvertor copyPoint) { + private ShowRevisionSelector(SvnBranchPointsCalculator.WrapperInvertor copyPoint) { super("show revisions to merge", Where.AWT); myCopyPoint = copyPoint; } @@ -676,11 +676,11 @@ public class QuickMerge { private class LocalChangesPrompt extends TaskDescriptor { private final boolean myMergeAll; @Nullable private final List myLists; - private final SvnBranchPointsCalculator.WrapperInvertor myCopyPoint; + private final SvnBranchPointsCalculator.WrapperInvertor myCopyPoint; private LocalChangesPrompt(final boolean mergeAll, @Nullable final List lists, - @Nullable SvnBranchPointsCalculator.WrapperInvertor copyPoint) { + @Nullable SvnBranchPointsCalculator.WrapperInvertor copyPoint) { super("local changes intersection check", Where.AWT); myMergeAll = mergeAll; myLists = lists; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java index 5d7bd6d3aa61..731f94511f16 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java @@ -43,7 +43,7 @@ import java.util.*; public class SvnBranchPointsCalculator { private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator"); - private FactsCalculator, SVNException> myCalculator; + private FactsCalculator myCalculator; private PersistentHolder myPersistentHolder; private File myFile; private final Project myProject; @@ -58,19 +58,19 @@ public class SvnBranchPointsCalculator { } public void activate() { - ValueHolder, KeyData> cache = null; + ValueHolder cache = null; myPersistentHolder = new PersistentHolder(myFile); - cache = new ValueHolder, KeyData>() { - public WrapperInvertor getValue(KeyData dataHolder) { - final WrapperInvertor result = + cache = new ValueHolder() { + public WrapperInvertor getValue(KeyData dataHolder) { + final WrapperInvertor result = myPersistentHolder.getBestHit(dataHolder.getRepoUrl(), dataHolder.getSourceUrl(), dataHolder.getTargetUrl()); if (LOG.isDebugEnabled()) { LOG.debug("Persistent for: " + dataHolder.toString() + " returned: " + (result == null ? null : result.toString())); } return result; } - public void setValue(WrapperInvertor value, KeyData dataHolder) { + public void setValue(WrapperInvertor value, KeyData dataHolder) { if (LOG.isDebugEnabled()) { LOG.debug("Put into persistent: key: " + dataHolder.toString() + " value: " + value.toString()); } @@ -78,7 +78,7 @@ public class SvnBranchPointsCalculator { } }; - myCalculator = new FactsCalculator, SVNException>( + myCalculator = new FactsCalculator( myProject, "Looking for branch origin", cache, new Loader(myProject)); } @@ -118,11 +118,11 @@ public class SvnBranchPointsCalculator { } } - public static class WrapperInvertor> { - private final T myWrapped; + public static class WrapperInvertor { + private final BranchCopyData myWrapped; private final boolean myInvertedSense; - public WrapperInvertor(boolean invertedSense, T wrapped) { + public WrapperInvertor(boolean invertedSense, BranchCopyData wrapped) { myInvertedSense = invertedSense; myWrapped = wrapped; } @@ -131,15 +131,15 @@ public class SvnBranchPointsCalculator { return myInvertedSense; } - public T getWrapped() { + public BranchCopyData getWrapped() { return myWrapped; } - public T getTrue() { + public BranchCopyData getTrue() { return myInvertedSense ? myWrapped.invertSelf() : myWrapped; } - public T inverted() { + public BranchCopyData inverted() { return myWrapped.invertSelf(); } @@ -200,7 +200,7 @@ public class SvnBranchPointsCalculator { } @Nullable - public WrapperInvertor getBestHit(final String repoUrl, final String source, final String target) { + public WrapperInvertor getBestHit(final String repoUrl, final String source, final String target) { final List keys; synchronized (myLock) { keys = (List) myForSearchMap.get(repoUrl); @@ -217,14 +217,14 @@ public class SvnBranchPointsCalculator { final boolean sourceIsOut = sourceMatching == null; if (sourceIsOut || targetMatching == null) { // if found by "target" url - we correctly thought that target of copy is target - return sourceIsOut ? new WrapperInvertor(false, map.get(targetMatching)) : - new WrapperInvertor(true, map.get(sourceMatching)); + return sourceIsOut ? new WrapperInvertor(false, map.get(targetMatching)) : + new WrapperInvertor(true, map.get(sourceMatching)); } final BranchCopyData sourceData = map.get(sourceMatching); final BranchCopyData targetData = map.get(targetMatching); final boolean inverted = sourceData.getTargetRevision() > targetData.getTargetRevision(); - return new WrapperInvertor(inverted, inverted ? sourceData : targetData); + return new WrapperInvertor(inverted, inverted ? sourceData : targetData); } } @@ -240,7 +240,7 @@ public class SvnBranchPointsCalculator { } } - private static class Loader implements ThrowableConvertor, SVNException> { + private static class Loader implements ThrowableConvertor { private SvnVcs myVcs; private Loader(final Project project) { @@ -248,7 +248,7 @@ public class SvnBranchPointsCalculator { } @Override - public WrapperInvertor convert(final KeyData keyData) throws SVNException { + public WrapperInvertor convert(final KeyData keyData) throws SVNException { final TransparentlyFailedValue consumer = new TransparentlyFailedValue(); new FirstInBranch(myVcs, keyData.getRepoUrl(), keyData.getTargetUrl(), keyData.getSourceUrl(), consumer).run(); @@ -263,7 +263,7 @@ public class SvnBranchPointsCalculator { branchCopyData = new BranchCopyData(keyData.getTargetUrl(), copyData.getCopySourceRevision(), keyData.getSourceUrl(), copyData.getCopyTargetRevision()); } - WrapperInvertor invertor = new WrapperInvertor(! correct, branchCopyData); + WrapperInvertor invertor = new WrapperInvertor(! correct, branchCopyData); if (LOG.isDebugEnabled()) { LOG.debug("Loader17 returned: for key: " + keyData.toString() + " result: " + (invertor.toString())); } @@ -349,7 +349,7 @@ public class SvnBranchPointsCalculator { } public TaskDescriptor getFirstCopyPointTask(final String repoUID, final String sourceUrl, final String targetUrl, - final Consumer, SVNException>> consumer) { + final Consumer> consumer) { return myCalculator.getTask(new KeyData(repoUID, sourceUrl, targetUrl), consumer, SVNException.class); } } From 21047415bf5f4b78693cb8af001bba6385473147 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 15 Apr 2014 22:33:51 +0400 Subject: [PATCH 05/65] svn: Removed unnecessary SvnBranchPointsCalculator.Invertor interface --- .../idea/svn/dialogs/SvnBranchPointsCalculator.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java index 731f94511f16..bfa11c7e59d6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java @@ -305,7 +305,7 @@ public class SvnBranchPointsCalculator { } } - public static class BranchCopyData implements Invertor { + public static class BranchCopyData { private final String mySource; private final String myTarget; private final long mySourceRevision; @@ -344,10 +344,6 @@ public class SvnBranchPointsCalculator { } } - private interface Invertor { - T invertSelf(); - } - public TaskDescriptor getFirstCopyPointTask(final String repoUID, final String sourceUrl, final String targetUrl, final Consumer> consumer) { return myCalculator.getTask(new KeyData(repoUID, sourceUrl, targetUrl), consumer, SVNException.class); From ef8bad7896ccb5493057d4c0927ba710b9796d2d Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 16 Apr 2014 16:12:27 +0400 Subject: [PATCH 06/65] svn: Refactored FirstInBranch - code simplifications, warnings fixes --- .../idea/svn/history/FirstInBranch.java | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java index 7fb35d14ca4d..f7ed42675e9d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java @@ -51,7 +51,7 @@ public class FirstInBranch implements Runnable { myTrunkUrl = relativePath(repositoryRoot, trunkUrl); } - private String relativePath(final String parent, final String child) { + private static String relativePath(final String parent, final String child) { String path = SVNPathUtil.getRelativePath(parent, child); return path.startsWith("/") ? path : "/" + path; } @@ -60,7 +60,7 @@ public class FirstInBranch implements Runnable { final Set exceptions = new HashSet(); final boolean [] called = new boolean[1]; try { - createTask(SVNURL.parseURIDecoded(myRepositoryRoot), exceptions).consume(new Consumer() { + run(SVNURL.parseURIDecoded(myRepositoryRoot), exceptions, new Consumer() { @Override public void consume(CopyData data) { if (data != null) { @@ -87,27 +87,27 @@ public class FirstInBranch implements Runnable { } } - private Consumer> createTask(final SVNURL branchURL, final Set exceptions) { - return new Consumer>() { - public void consume(final Consumer copyDataConsumer) { - final SVNLogClient logClient = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public SVNLogClient compute() { - if (myVcs.getProject().isDisposed()) return null; - return myVcs.createLogClient(); - } - }); - if (logClient == null) return; - try { - logClient.doLog(branchURL, null, SVNRevision.UNDEFINED, SVNRevision.HEAD, SVNRevision.create(0), false, true, -1, - new MyLogEntryHandler(copyDataConsumer, myTrunkUrl, myBranchUrl)); - } catch (SVNCancelException e) { - // - } catch (SVNException e) { - exceptions.add(e); - } + private void run(final SVNURL branchURL, + final Set exceptions, + final Consumer copyDataConsumer) { + final SVNLogClient logClient = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public SVNLogClient compute() { + if (myVcs.getProject().isDisposed()) return null; + return myVcs.createLogClient(); } - }; + }); + if (logClient == null) return; + try { + logClient.doLog(branchURL, null, SVNRevision.UNDEFINED, SVNRevision.HEAD, SVNRevision.create(0), false, true, -1, + new MyLogEntryHandler(copyDataConsumer, myTrunkUrl, myBranchUrl)); + } + catch (SVNCancelException e) { + // + } + catch (SVNException e) { + exceptions.add(e); + } } private static class MyLogEntryHandler implements ISVNLogEntryHandler { From 281cc564b5d291f685bee8d3c4260b9cb0433c0b Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 16 Apr 2014 17:46:48 +0400 Subject: [PATCH 07/65] svn: Refactored FirstInBranch - not null, code simplifications (exception handling) --- .../idea/svn/history/FirstInBranch.java | 81 ++++++++++--------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java index f7ed42675e9d..cd7f622aa431 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java @@ -20,7 +20,8 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vcs.changes.TransparentlyFailedValueI; import com.intellij.util.Consumer; -import com.intellij.util.containers.hash.HashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.SvnVcs; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; @@ -28,21 +29,22 @@ import org.tmatesoft.svn.core.wc.SVNLogClient; import org.tmatesoft.svn.core.wc.SVNRevision; import java.util.Map; -import java.util.Set; // TODO: This one seem to determine revision in which branch was created - copied from trunk. // TODO: This could be done in one command "svn log -r 0:HEAD --stop-on-copy --limit 1". // TODO: Check for 1.7 and rewrite using this approach. public class FirstInBranch implements Runnable { - private final SvnVcs myVcs; - private final String myBranchUrl; - private final String myTrunkUrl; - private final String myRepositoryRoot; - private final TransparentlyFailedValueI myConsumer; + private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.history.FirstInBranch"); - public FirstInBranch(final SvnVcs vcs, final String repositoryRoot, final String branchUrl, final String trunkUrl, - final TransparentlyFailedValueI consumer) { + @NotNull private final SvnVcs myVcs; + @NotNull private final String myBranchUrl; + @NotNull private final String myTrunkUrl; + @NotNull private final String myRepositoryRoot; + @NotNull private final TransparentlyFailedValueI myConsumer; + + public FirstInBranch(@NotNull SvnVcs vcs, @NotNull String repositoryRoot, @NotNull String branchUrl, @NotNull String trunkUrl, + @NotNull TransparentlyFailedValueI consumer) { myVcs = vcs; myRepositoryRoot = repositoryRoot; myConsumer = consumer; @@ -53,43 +55,50 @@ public class FirstInBranch implements Runnable { private static String relativePath(final String parent, final String child) { String path = SVNPathUtil.getRelativePath(parent, child); - return path.startsWith("/") ? path : "/" + path; + + return SvnUtil.ensureStartSlash(path); + } + + private SVNURL getRepositoryRootUrl() { + SVNURL result = null; + + try { + result = SVNURL.parseURIDecoded(myRepositoryRoot); + } + catch (SVNException e) { + LOG.info(e); + myConsumer.fail(e); + } + + return result; } public void run() { - final Set exceptions = new HashSet(); - final boolean [] called = new boolean[1]; + SVNURL repositoryRootUrl = getRepositoryRootUrl(); + + if (repositoryRootUrl != null) { + run(repositoryRootUrl); + } + } + + private void run(@NotNull SVNURL url) { try { - run(SVNURL.parseURIDecoded(myRepositoryRoot), exceptions, new Consumer() { + run(url, new Consumer() { @Override public void consume(CopyData data) { if (data != null) { myConsumer.set(data); - called[0] = true; } } }); } catch (SVNException e) { + LOG.info(e); myConsumer.fail(e); - return; - } - if (called[0]) return; - - if (! exceptions.isEmpty()) { - LOG.info("Wasn't able to find branch point, exception(s) below"); - for (SVNException exception : exceptions) { - LOG.info(exception); - } - myConsumer.fail(exceptions.iterator().next()); - } else if (! called[0]) { - myConsumer.set(null); } } - private void run(final SVNURL branchURL, - final Set exceptions, - final Consumer copyDataConsumer) { + private void run(@NotNull SVNURL branchURL, @NotNull Consumer copyDataConsumer) throws SVNException { final SVNLogClient logClient = ApplicationManager.getApplication().runReadAction(new Computable() { @Override public SVNLogClient compute() { @@ -103,19 +112,17 @@ public class FirstInBranch implements Runnable { new MyLogEntryHandler(copyDataConsumer, myTrunkUrl, myBranchUrl)); } catch (SVNCancelException e) { - // - } - catch (SVNException e) { - exceptions.add(e); + // process cancelled - do nothing } } private static class MyLogEntryHandler implements ISVNLogEntryHandler { - private final SvnPathThroughHistoryCorrection myTrunkCorrector; - private final SvnPathThroughHistoryCorrection myBranchCorrector; - private final Consumer myCopyDataConsumer; - public MyLogEntryHandler(Consumer copyDataConsumer, String trunkUrl, String branchUrl) { + @NotNull private final SvnPathThroughHistoryCorrection myTrunkCorrector; + @NotNull private final SvnPathThroughHistoryCorrection myBranchCorrector; + @NotNull private final Consumer myCopyDataConsumer; + + public MyLogEntryHandler(@NotNull Consumer copyDataConsumer, @NotNull String trunkUrl, @NotNull String branchUrl) { myCopyDataConsumer = copyDataConsumer; myTrunkCorrector = new SvnPathThroughHistoryCorrection(trunkUrl); myBranchCorrector = new SvnPathThroughHistoryCorrection(branchUrl); From 372a664f3c54e960aca28250f6b942a4bc5562c6 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 16 Apr 2014 18:38:14 +0400 Subject: [PATCH 08/65] svn: Refactored SvnMergeInfoCache - removed inner MyState class (fields added directly to SvnMergeInfoCache) --- .../idea/svn/mergeinfo/SvnMergeInfoCache.java | 32 +++++-------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java index d9ad5a371fd0..62c3ce08bbe1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java @@ -23,6 +23,7 @@ import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.vcs.changes.TransparentlyFailedValue; import com.intellij.openapi.vcs.changes.TransparentlyFailedValueI; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.SoftHashMap; import com.intellij.util.messages.Topic; import org.jetbrains.annotations.Nullable; @@ -34,21 +35,20 @@ import org.jetbrains.idea.svn.history.FirstInBranch; import org.jetbrains.idea.svn.history.SvnChangeList; import org.tmatesoft.svn.core.SVNException; -import java.util.HashMap; import java.util.Map; public class SvnMergeInfoCache { private final static Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.mergeinfo.SvnMergeInfoCache"); private final Project myProject; - private final MyState myState; + private final Map myCurrentUrlMapping; public static Topic SVN_MERGE_INFO_CACHE = new Topic("SVN_MERGE_INFO_CACHE", SvnMergeInfoCacheListener.class); private SvnMergeInfoCache(final Project project) { myProject = project; - myState = new MyState(); + myCurrentUrlMapping = ContainerUtil.newHashMap(); } public static SvnMergeInfoCache getInstance(final Project project) { @@ -58,7 +58,7 @@ public class SvnMergeInfoCache { public void clear(final WCPaths info, final String branchPath) { final String currentUrl = info.getRootUrl(); - final MyCurrentUrlData rootMapping = myState.getCurrentUrlMapping().get(currentUrl); + final MyCurrentUrlData rootMapping = myCurrentUrlMapping.get(currentUrl); if (rootMapping != null) { final BranchInfo mergeChecker = rootMapping.getBranchInfo(branchPath); if (mergeChecker != null) { @@ -71,7 +71,7 @@ public class SvnMergeInfoCache { public MergeinfoCached getCachedState(final WCPaths info, final String branchPath) { final String currentUrl = info.getRootUrl(); - MyCurrentUrlData rootMapping = myState.getCurrentUrlMapping().get(currentUrl); + MyCurrentUrlData rootMapping = myCurrentUrlMapping.get(currentUrl); if (rootMapping != null) { final BranchInfo branchInfo = rootMapping.getBranchInfo(branchPath); if (branchInfo != null) { @@ -92,11 +92,11 @@ public class SvnMergeInfoCache { final String currentUrl = info.getRootUrl(); final String branchUrl = selectedBranch.getUrl(); - MyCurrentUrlData rootMapping = myState.getCurrentUrlMapping().get(currentUrl); + MyCurrentUrlData rootMapping = myCurrentUrlMapping.get(currentUrl); BranchInfo mergeChecker = null; if (rootMapping == null) { rootMapping = new MyCurrentUrlData(); - myState.getCurrentUrlMapping().put(currentUrl, rootMapping); + myCurrentUrlMapping.put(currentUrl, rootMapping); } else { mergeChecker = rootMapping.getBranchInfo(branchPath); } @@ -110,7 +110,7 @@ public class SvnMergeInfoCache { public boolean isMixedRevisions(final WCInfoWithBranches info, final String branchPath) { final String currentUrl = info.getRootUrl(); - final MyCurrentUrlData rootMapping = myState.getCurrentUrlMapping().get(currentUrl); + final MyCurrentUrlData rootMapping = myCurrentUrlMapping.get(currentUrl); if (rootMapping != null) { final BranchInfo branchInfo = rootMapping.getBranchInfo(branchPath); if (branchInfo != null) { @@ -120,22 +120,6 @@ public class SvnMergeInfoCache { return false; } - private static class MyState { - private Map myCurrentUrlMapping; - - private MyState() { - myCurrentUrlMapping = new HashMap(); - } - - public Map getCurrentUrlMapping() { - return myCurrentUrlMapping; - } - - public void setCurrentUrlMapping(final Map currentUrlMapping) { - myCurrentUrlMapping = currentUrlMapping; - } - } - public static enum MergeCheckResult { COMMON, MERGED, From 1d33a57ef81b2b1042c75d88be4d571ef3e60df0 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 16 Apr 2014 18:47:37 +0400 Subject: [PATCH 09/65] svn: Refactored FirstInBranch - use common client factory model (instead of direct SVNLogClient usage) --- .../idea/svn/dialogs/QuickMerge.java | 26 ++++++------- .../dialogs/SvnBranchPointsCalculator.java | 16 ++++---- .../idea/svn/history/FirstInBranch.java | 39 ++++++++++++------- .../idea/svn/mergeinfo/SvnMergeInfoCache.java | 10 ++--- 4 files changed, 50 insertions(+), 41 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java index f081229a868b..bcc77525f45b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java @@ -353,16 +353,16 @@ public class QuickMerge { queue.add(mergeAllExecutor); } - private class MergeAllWithBranchCopyPoint extends TaskDescriptor implements Consumer> { - private final AtomicReference> myData; + private class MergeAllWithBranchCopyPoint extends TaskDescriptor implements Consumer> { + private final AtomicReference> myData; private MergeAllWithBranchCopyPoint() { super("merge all", Where.AWT); - myData = new AtomicReference>(); + myData = new AtomicReference>(); } @Override - public void consume(TransparentlyFailedValueI value) { + public void consume(TransparentlyFailedValueI value) { myData.set(value); } @@ -370,7 +370,7 @@ public class QuickMerge { public void run(ContinuationContext context) { SvnBranchPointsCalculator.WrapperInvertor invertor; try { - final TransparentlyFailedValueI + final TransparentlyFailedValueI transparentlyFailedValueI = myData.get(); if (transparentlyFailedValueI == null) { finishWithError(context, "Merge start wasn't found", true); @@ -378,8 +378,8 @@ public class QuickMerge { } invertor = transparentlyFailedValueI.get(); } - catch (SVNException e) { - finishWithError(context, "Merge start wasn't found", Collections.singletonList(new VcsException(e))); + catch (VcsException e) { + finishWithError(context, "Merge start wasn't found", Collections.singletonList(e)); return; } if (invertor == null) { @@ -532,13 +532,13 @@ public class QuickMerge { } private class MergeCalculator extends TaskDescriptor implements - Consumer> { + Consumer> { private final static String ourOneShotStrategy = "svn.quickmerge.oneShotStrategy"; private final WCInfo myWcInfo; private final String mySourceUrl; private final String myBranchName; private final - AtomicReference> + AtomicReference> myCopyData; private boolean myIsReintegrate; @@ -547,7 +547,7 @@ public class QuickMerge { private final MergeChecker myMergeChecker; @Override - public void consume(TransparentlyFailedValueI value) { + public void consume(TransparentlyFailedValueI value) { myCopyData.set(value); } @@ -566,7 +566,7 @@ public class QuickMerge { myWcInfo.getRootUrl(), mySourceUrl, mySourceUrl, myVcs.createWCClient())); }*/ - myCopyData = new AtomicReference>(); + myCopyData = new AtomicReference>(); } //"Calculating not merged revisions" @@ -576,8 +576,8 @@ public class QuickMerge { try { copyDataValue = myCopyData.get().get(); } - catch (SVNException e) { - finishWithError(context, "Merge start wasn't found", Collections.singletonList(new VcsException(e))); + catch (VcsException e) { + finishWithError(context, "Merge start wasn't found", Collections.singletonList(e)); return; } if (copyDataValue == null) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java index bfa11c7e59d6..600eb1a04e71 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnBranchPointsCalculator.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.svn.dialogs; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.TransparentlyFailedValue; import com.intellij.openapi.vcs.changes.TransparentlyFailedValueI; import com.intellij.openapi.vcs.persistent.SmallMapSerializer; @@ -33,7 +34,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.history.CopyData; import org.jetbrains.idea.svn.history.FirstInBranch; -import org.tmatesoft.svn.core.SVNException; import java.io.DataInput; import java.io.DataOutput; @@ -43,7 +43,7 @@ import java.util.*; public class SvnBranchPointsCalculator { private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator"); - private FactsCalculator myCalculator; + private FactsCalculator myCalculator; private PersistentHolder myPersistentHolder; private File myFile; private final Project myProject; @@ -78,7 +78,7 @@ public class SvnBranchPointsCalculator { } }; - myCalculator = new FactsCalculator( + myCalculator = new FactsCalculator( myProject, "Looking for branch origin", cache, new Loader(myProject)); } @@ -240,7 +240,7 @@ public class SvnBranchPointsCalculator { } } - private static class Loader implements ThrowableConvertor { + private static class Loader implements ThrowableConvertor { private SvnVcs myVcs; private Loader(final Project project) { @@ -248,8 +248,8 @@ public class SvnBranchPointsCalculator { } @Override - public WrapperInvertor convert(final KeyData keyData) throws SVNException { - final TransparentlyFailedValue consumer = new TransparentlyFailedValue(); + public WrapperInvertor convert(final KeyData keyData) throws VcsException { + final TransparentlyFailedValue consumer = new TransparentlyFailedValue(); new FirstInBranch(myVcs, keyData.getRepoUrl(), keyData.getTargetUrl(), keyData.getSourceUrl(), consumer).run(); final CopyData copyData = consumer.get(); @@ -345,7 +345,7 @@ public class SvnBranchPointsCalculator { } public TaskDescriptor getFirstCopyPointTask(final String repoUID, final String sourceUrl, final String targetUrl, - final Consumer> consumer) { - return myCalculator.getTask(new KeyData(repoUID, sourceUrl, targetUrl), consumer, SVNException.class); + final Consumer> consumer) { + return myCalculator.getTask(new KeyData(repoUID, sourceUrl, targetUrl), consumer, VcsException.class); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java index cd7f622aa431..f871ee09855a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java @@ -18,15 +18,17 @@ package org.jetbrains.idea.svn.history; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.TransparentlyFailedValueI; import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; -import org.tmatesoft.svn.core.wc.SVNLogClient; import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; import java.util.Map; @@ -41,10 +43,10 @@ public class FirstInBranch implements Runnable { @NotNull private final String myBranchUrl; @NotNull private final String myTrunkUrl; @NotNull private final String myRepositoryRoot; - @NotNull private final TransparentlyFailedValueI myConsumer; + @NotNull private final TransparentlyFailedValueI myConsumer; public FirstInBranch(@NotNull SvnVcs vcs, @NotNull String repositoryRoot, @NotNull String branchUrl, @NotNull String trunkUrl, - @NotNull TransparentlyFailedValueI consumer) { + @NotNull TransparentlyFailedValueI consumer) { myVcs = vcs; myRepositoryRoot = repositoryRoot; myConsumer = consumer; @@ -63,9 +65,9 @@ public class FirstInBranch implements Runnable { SVNURL result = null; try { - result = SVNURL.parseURIDecoded(myRepositoryRoot); + result = SvnUtil.createUrl(myRepositoryRoot); } - catch (SVNException e) { + catch (SvnBindException e) { LOG.info(e); myConsumer.fail(e); } @@ -92,27 +94,34 @@ public class FirstInBranch implements Runnable { } }); } - catch (SVNException e) { + catch (VcsException e) { LOG.info(e); myConsumer.fail(e); } } - private void run(@NotNull SVNURL branchURL, @NotNull Consumer copyDataConsumer) throws SVNException { - final SVNLogClient logClient = ApplicationManager.getApplication().runReadAction(new Computable() { + private void run(@NotNull SVNURL branchURL, @NotNull Consumer copyDataConsumer) throws VcsException { + final SvnTarget target = SvnTarget.fromURL(branchURL); + + HistoryClient client = ApplicationManager.getApplication().runReadAction(new Computable() { @Override - public SVNLogClient compute() { + public HistoryClient compute() { if (myVcs.getProject().isDisposed()) return null; - return myVcs.createLogClient(); + return myVcs.getFactory(target).createHistoryClient(); } }); - if (logClient == null) return; + + if (client == null) return; + try { - logClient.doLog(branchURL, null, SVNRevision.UNDEFINED, SVNRevision.HEAD, SVNRevision.create(0), false, true, -1, - new MyLogEntryHandler(copyDataConsumer, myTrunkUrl, myBranchUrl)); + client.doLog(target, SVNRevision.HEAD, SVNRevision.create(0), false, true, false, -1, null, + new MyLogEntryHandler(copyDataConsumer, myTrunkUrl, myBranchUrl)); } - catch (SVNCancelException e) { - // process cancelled - do nothing + catch (SvnBindException e) { + // do not throw cancel exception as this means corresponding copy point is found (if progress indicator was not explicitly cancelled) + if (!e.contains(SVNErrorCode.CANCELLED)) { + throw e; + } } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java index 62c3ce08bbe1..742e3951aa72 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java @@ -20,6 +20,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.TransparentlyFailedValue; import com.intellij.openapi.vcs.changes.TransparentlyFailedValueI; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; @@ -33,7 +34,6 @@ import org.jetbrains.idea.svn.dialogs.WCPaths; import org.jetbrains.idea.svn.history.CopyData; import org.jetbrains.idea.svn.history.FirstInBranch; import org.jetbrains.idea.svn.history.SvnChangeList; -import org.tmatesoft.svn.core.SVNException; import java.util.Map; @@ -43,8 +43,8 @@ public class SvnMergeInfoCache { private final Project myProject; private final Map myCurrentUrlMapping; - public static Topic SVN_MERGE_INFO_CACHE = new Topic("SVN_MERGE_INFO_CACHE", - SvnMergeInfoCacheListener.class); + public static Topic SVN_MERGE_INFO_CACHE = + new Topic("SVN_MERGE_INFO_CACHE", SvnMergeInfoCacheListener.class); private SvnMergeInfoCache(final Project project) { myProject = project; @@ -144,7 +144,7 @@ public class SvnMergeInfoCache { myPath = path; myRevision = -1; - final TransparentlyFailedValueI result = new TransparentlyFailedValue() { + final TransparentlyFailedValueI result = new TransparentlyFailedValue() { @Override public void set(CopyData copyData) { if (copyData == null) return; @@ -160,7 +160,7 @@ public class SvnMergeInfoCache { } @Override - public void fail(SVNException e) { + public void fail(VcsException e) { LOG.info(e); VcsBalloonProblemNotifier.showOverChangesView(vcs.getProject(), e.getMessage(), MessageType.ERROR); } From a95c8b40142a88a589233c8e651141f382a325b0 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 16 Apr 2014 22:04:16 +0400 Subject: [PATCH 10/65] svn: Refactored DefaultConfigLoader - use common client factory model (instead of direct SVNLogClient usage) --- .../svn/branchConfig/DefaultConfigLoader.java | 46 +++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java index 914a8ebd6746..9b4222e480b9 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java @@ -17,16 +17,18 @@ package org.jetbrains.idea.svn.branchConfig; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.integrate.SvnBranchItem; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.wc.SVNInfo; -import org.tmatesoft.svn.core.wc.SVNLogClient; import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; import java.util.ArrayList; @@ -59,25 +61,10 @@ public class DefaultConfigLoader { while(true) { final String s = SVNPathUtil.tail(baseUrl.getPath()); if (s.equalsIgnoreCase(DEFAULT_TRUNK_NAME) || s.equalsIgnoreCase(DEFAULT_BRANCHES_NAME) || s.equalsIgnoreCase(DEFAULT_TAGS_NAME)) { - final SVNURL rootPath = baseUrl.removePathTail(); - SVNLogClient client = vcs.createLogClient(); - client.doList(rootPath, SVNRevision.UNDEFINED, SVNRevision.HEAD, false, false, new ISVNDirEntryHandler() { - public void handleDirEntry(final SVNDirEntry dirEntry) throws SVNException { - if (("".equals(dirEntry.getRelativePath())) || (! SVNNodeKind.DIR.equals(dirEntry.getKind()))) { - // do not use itself or files - return; - } - - if (dirEntry.getName().toLowerCase().endsWith(DEFAULT_TRUNK_NAME)) { - result.setTrunkUrl(rootPath.appendPath(dirEntry.getName(), false).toString()); - } - else { - result.addBranches(rootPath.appendPath(dirEntry.getName(), false).toString(), - new InfoStorage>(new ArrayList(0), InfoReliability.defaultValues)); - } - } - }); + SVNURL rootPath = baseUrl.removePathTail(); + SvnTarget target = SvnTarget.fromURL(rootPath); + vcs.getFactory(target).createBrowseClient().list(target, SVNRevision.HEAD, SVNDepth.IMMEDIATES, createHandler(result, rootPath)); break; } if (SVNPathUtil.removeTail(baseUrl.getPath()).length() == 0) { @@ -91,5 +78,26 @@ public class DefaultConfigLoader { LOG.info(e); return null; } + catch (VcsException e) { + LOG.info(e); + return null; + } + } + + @NotNull + private static ISVNDirEntryHandler createHandler(final SvnBranchConfigurationNew result, final SVNURL rootPath) { + return new ISVNDirEntryHandler() { + public void handleDirEntry(final SVNDirEntry dirEntry) throws SVNException { + if (SVNNodeKind.DIR.equals(dirEntry.getKind())) { + if (dirEntry.getName().toLowerCase().endsWith(DEFAULT_TRUNK_NAME)) { + result.setTrunkUrl(rootPath.appendPath(dirEntry.getName(), false).toString()); + } + else { + result.addBranches(rootPath.appendPath(dirEntry.getName(), false).toString(), + new InfoStorage>(new ArrayList(0), InfoReliability.defaultValues)); + } + } + } + }; } } From d8991919c17fbe563d9c26c0ff56478615032f95 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 16 Apr 2014 22:17:51 +0400 Subject: [PATCH 11/65] svn: Make sure start() method of the task queue (myBranchesLoader) in SvnBranchConfigurationManager is invoked - otherwise runnables passed to queue are not executed --- .../idea/svn/SvnBranchConfigurationManager.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java index 65e9028c8185..6a25f57cf906 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java @@ -71,6 +71,22 @@ public class SvnBranchConfigurationManager implements PersistentStateComponent Date: Fri, 18 Apr 2014 13:21:53 +0400 Subject: [PATCH 12/65] svn: Refactored DefaultConfigLoader - code simplifications, warnings fixes --- .../idea/svn/branchConfig/DefaultConfigLoader.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java index 9b4222e480b9..315954e7b520 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/DefaultConfigLoader.java @@ -17,6 +17,7 @@ package org.jetbrains.idea.svn.branchConfig; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NonNls; @@ -35,7 +36,9 @@ import java.util.ArrayList; import java.util.List; public class DefaultConfigLoader { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.DefaultConfigLoader"); + @NonNls private static final String DEFAULT_TRUNK_NAME = "trunk"; @NonNls private static final String DEFAULT_BRANCHES_NAME = "branches"; @NonNls private static final String DEFAULT_TAGS_NAME = "tags"; @@ -89,11 +92,13 @@ public class DefaultConfigLoader { return new ISVNDirEntryHandler() { public void handleDirEntry(final SVNDirEntry dirEntry) throws SVNException { if (SVNNodeKind.DIR.equals(dirEntry.getKind())) { - if (dirEntry.getName().toLowerCase().endsWith(DEFAULT_TRUNK_NAME)) { - result.setTrunkUrl(rootPath.appendPath(dirEntry.getName(), false).toString()); + SVNURL childUrl = rootPath.appendPath(dirEntry.getName(), false); + + if (StringUtil.endsWithIgnoreCase(dirEntry.getName(), DEFAULT_TRUNK_NAME)) { + result.setTrunkUrl(childUrl.toString()); } else { - result.addBranches(rootPath.appendPath(dirEntry.getName(), false).toString(), + result.addBranches(childUrl.toString(), new InfoStorage>(new ArrayList(0), InfoReliability.defaultValues)); } } From 482733a382071a60b4fd725d7884bf050784b836 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 18 Apr 2014 17:17:07 +0400 Subject: [PATCH 13/65] svn: Refactored LatestExistentSearcher - use common client factory model (instead of direct SVNLogClient usage) --- .../svn/history/LatestExistentSearcher.java | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LatestExistentSearcher.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LatestExistentSearcher.java index b878d60664a7..8aaec2aad6d0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LatestExistentSearcher.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LatestExistentSearcher.java @@ -15,8 +15,11 @@ */ package org.jetbrains.idea.svn.history; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Ref; +import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.RootUrlInfo; import org.jetbrains.idea.svn.SvnFileUrlMapping; @@ -25,10 +28,14 @@ import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.wc.SVNInfo; import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; import java.util.Map; public class LatestExistentSearcher { + + private static final Logger LOG = Logger.getInstance(LatestExistentSearcher.class); + private long myStartNumber; private boolean myStartExistsKnown; private final SVNURL myUrl; @@ -67,24 +74,18 @@ public class LatestExistentSearcher { final String urlRelativeString = myUrl.toString().substring(repRoot.toString().length()); final SVNRevision startRevision = SVNRevision.create(myStartNumber); - myVcs.createLogClient().doLog(existingParent, new String[]{""}, startRevision, startRevision, SVNRevision.HEAD, false, true, 0, - new ISVNLogEntryHandler() { - public void handleLogEntry(final SVNLogEntry logEntry) throws SVNException { - final Map changedPaths = logEntry.getChangedPaths(); - for (Object o : changedPaths.values()) { - final SVNLogEntryPath path = (SVNLogEntryPath) o; - if ((path.getType() == 'D') && (urlRelativeString.equals(path.getPath()))) { - latest.set(logEntry.getRevision()); - throw new SVNException(SVNErrorMessage.UNKNOWN_ERROR_MESSAGE); - } - } - } - }); + SvnTarget target = SvnTarget.fromURL(existingParent, startRevision); + myVcs.getFactory(target).createHistoryClient() + .doLog(target, startRevision, SVNRevision.HEAD, false, true, false, 0, null, createHandler(latest, urlRelativeString)); } } catch (SVNException e) { - // - } finally { + LOG.info(e); + } + catch (VcsException e) { + LOG.info(e); + } + finally { if (repository != null) { repository.closeSession(); } @@ -93,6 +94,22 @@ public class LatestExistentSearcher { return latest.get().longValue(); } + @NotNull + private static ISVNLogEntryHandler createHandler(@NotNull final Ref latest, @NotNull final String urlRelativeString) { + return new ISVNLogEntryHandler() { + public void handleLogEntry(final SVNLogEntry logEntry) throws SVNException { + final Map changedPaths = logEntry.getChangedPaths(); + for (Object o : changedPaths.values()) { + final SVNLogEntryPath path = (SVNLogEntryPath)o; + if ((path.getType() == 'D') && (urlRelativeString.equals(path.getPath()))) { + latest.set(logEntry.getRevision()); + throw new SVNException(SVNErrorMessage.UNKNOWN_ERROR_MESSAGE); + } + } + } + }; + } + public long getLatestExistent() { if (! detectStartRevision()) return myStartNumber; From e62ad7288c9aec420285d73a37c6f42416292b36 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 18 Apr 2014 17:18:51 +0400 Subject: [PATCH 14/65] svn: Refactored QuickMerge - merge parameters extracted to separate MergeContext class --- .../idea/svn/dialogs/CopiesPanel.java | 2 +- .../idea/svn/dialogs/MergeContext.java | 88 ++++++++++++ .../idea/svn/dialogs/QuickMerge.java | 126 +++++++++--------- .../jetbrains/idea/svn/SvnQuickMergeTest.java | 31 ++--- 4 files changed, 166 insertions(+), 81 deletions(-) create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/MergeContext.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java index e0101053ad80..37dd5a5230f4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java @@ -357,7 +357,7 @@ public class CopiesPanel { SelectBranchPopup.showForBranchRoot(myProject, root, new SelectBranchPopup.BranchSelectedCallback() { @Override public void branchSelected(Project project, SvnBranchConfigurationNew configuration, String url, long revision) { - new QuickMerge(project, url, wcInfo, SVNPathUtil.tail(url), root).execute(new QuickMergeInteractionImpl(myProject)); + new QuickMerge(new MergeContext(myVcs, url, wcInfo, SVNPathUtil.tail(url), root)).execute(new QuickMergeInteractionImpl(myProject)); } }, "Select branch", mergeLabel); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/MergeContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/MergeContext.java new file mode 100644 index 000000000000..bb60266aa85d --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/MergeContext.java @@ -0,0 +1,88 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.dialogs; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnVcs; + +/** + * @author Konstantin Kolosovsky. + */ +public class MergeContext { + + @NotNull private final Project myProject; + @NotNull private final String myBranchName; + @NotNull private final VirtualFile myRoot; + @NotNull private final WCInfo myWcInfo; + @NotNull private String mySourceUrl; + @NotNull private final SvnVcs myVcs; + @NotNull private final String myTitle; + + public MergeContext(@NotNull SvnVcs vcs, + @NotNull String sourceUrl, + @NotNull WCInfo wcInfo, + @NotNull String branchName, + @NotNull VirtualFile root) { + myVcs = vcs; + myProject = vcs.getProject(); + myBranchName = branchName; + myRoot = root; + mySourceUrl = sourceUrl; + myWcInfo = wcInfo; + myTitle = "Merge from " + myBranchName; + } + + @NotNull + public Project getProject() { + return myProject; + } + + @NotNull + public String getBranchName() { + return myBranchName; + } + + @NotNull + public VirtualFile getRoot() { + return myRoot; + } + + @NotNull + public WCInfo getWcInfo() { + return myWcInfo; + } + + @NotNull + public String getSourceUrl() { + return mySourceUrl; + } + + @NotNull + public SvnVcs getVcs() { + return myVcs; + } + + @NotNull + public String getTitle() { + return myTitle; + } + + public void setSourceUrl(@NotNull String sourceUrl) { + mySourceUrl = sourceUrl; + } +} \ No newline at end of file diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java index bcc77525f45b..36fae18f462f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java @@ -21,7 +21,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.util.PopupUtil; import com.intellij.openapi.util.Pair; @@ -32,7 +31,6 @@ import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager; import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.RefreshSessionImpl; import com.intellij.util.Consumer; import com.intellij.util.FilePathByPathComparator; @@ -69,27 +67,15 @@ import java.util.*; import java.util.concurrent.atomic.AtomicReference; public class QuickMerge { - private final Project myProject; - private final String myBranchName; - private final VirtualFile myRoot; - private WCInfo myWcInfo; - private String mySourceUrl; - private SvnVcs myVcs; - private final String myTitle; + + @NotNull private final MergeContext myMergeContext; private final Continuation myContinuation; private QuickMergeInteraction myInteraction; private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.dialogs.QuickMerge"); - public QuickMerge(Project project, String sourceUrl, WCInfo wcInfo, final String branchName, final VirtualFile root) { - myProject = project; - myBranchName = branchName; - myRoot = root; - myVcs = SvnVcs.getInstance(project); - mySourceUrl = sourceUrl; - myWcInfo = wcInfo; - myTitle = "Merge from " + myBranchName; - - myContinuation = Continuation.createFragmented(myProject, true); + public QuickMerge(@NotNull MergeContext mergeContext) { + myMergeContext = mergeContext; + myContinuation = Continuation.createFragmented(mergeContext.getProject(), true); } private class SourceUrlCorrection extends TaskDescriptor { @@ -99,12 +85,14 @@ public class QuickMerge { @Override public void run(ContinuationContext continuationContext) { - final SVNURL branch = SvnBranchConfigurationManager.getInstance(myProject).getSvnBranchConfigManager().getWorkingBranchWithReload(myWcInfo.getUrl(), myRoot); - if (branch != null && (! myWcInfo.getUrl().equals(branch))) { + final SVNURL branch = + SvnBranchConfigurationManager.getInstance(myMergeContext.getProject()).getSvnBranchConfigManager().getWorkingBranchWithReload( + myMergeContext.getWcInfo().getUrl(), myMergeContext.getRoot()); + if (branch != null && (!myMergeContext.getWcInfo().getUrl().equals(branch))) { final String branchString = branch.toString(); - if (SVNPathUtil.isAncestor(branchString, myWcInfo.getRootUrl())) { - final String subPath = SVNPathUtil.getRelativePath(branchString, myWcInfo.getRootUrl()); - mySourceUrl = SVNPathUtil.append(mySourceUrl, subPath); + if (SVNPathUtil.isAncestor(branchString, myMergeContext.getWcInfo().getRootUrl())) { + final String subPath = SVNPathUtil.getRelativePath(branchString, myMergeContext.getWcInfo().getRootUrl()); + myMergeContext.setSourceUrl(SVNPathUtil.append(myMergeContext.getSourceUrl(), subPath)); } } } @@ -122,7 +110,8 @@ public class QuickMerge { return; } - if (SVNURLUtil.isAncestor(url, myWcInfo.getUrl()) || SVNURLUtil.isAncestor(myWcInfo.getUrl(), url)) { + if (SVNURLUtil.isAncestor(url, myMergeContext.getWcInfo().getUrl()) || + SVNURLUtil.isAncestor(myMergeContext.getWcInfo().getUrl(), url)) { finishWithError(continuationContext, "Cannot merge from self", true); return; } @@ -137,7 +126,7 @@ public class QuickMerge { SVNURL url = null; try { - url = SvnUtil.createUrl(mySourceUrl); + url = SvnUtil.createUrl(myMergeContext.getSourceUrl()); } catch (SvnBindException e) { finishWithError(continuationContext, e.getMessage(), true); @@ -155,7 +144,8 @@ public class QuickMerge { @Override public void run(ContinuationContext context) { final List tasks = new LinkedList(); - final boolean supportsMergeinfo = myWcInfo.getFormat().supportsMergeInfo() && SvnUtil.checkRepositoryVersion15(myVcs, mySourceUrl); + final boolean supportsMergeinfo = myMergeContext.getWcInfo().getFormat().supportsMergeInfo() && SvnUtil.checkRepositoryVersion15( + myMergeContext.getVcs(), myMergeContext.getSourceUrl()); if (! supportsMergeinfo) { insertMergeAll(tasks); } else { @@ -168,7 +158,7 @@ public class QuickMerge { @CalledInAwt public void execute(@NotNull final QuickMergeInteraction interaction, @NotNull final TaskDescriptor... finalTasks) { myInteraction = interaction; - myInteraction.setTitle(myTitle); + myInteraction.setTitle(myMergeContext.getTitle()); FileDocumentManager.getInstance().saveAllDocuments(); @@ -183,13 +173,13 @@ public class QuickMerge { myContinuation.addExceptionHandler(VcsException.class, new Consumer() { @Override public void consume(VcsException e) { - myInteraction.showErrors(myTitle, Collections.singletonList(e)); + myInteraction.showErrors(myMergeContext.getTitle(), Collections.singletonList(e)); } }); myContinuation.addExceptionHandler(SVNException.class, new Consumer() { @Override public void consume(SVNException e) { - myInteraction.showErrors(myTitle, Collections.singletonList(new VcsException(e))); + myInteraction.showErrors(myMergeContext.getTitle(), Collections.singletonList(new VcsException(e))); } }); myContinuation.addExceptionHandler(RuntimeException.class, new Consumer() { @@ -215,7 +205,9 @@ public class QuickMerge { @Override public void consume(Long bunchSize, final MergeDialogI dialog) { final LoadRecentBranchRevisions loader = - new LoadRecentBranchRevisions(myBranchName, dialog.getLastNumber(), myWcInfo, myVcs, mySourceUrl, bunchSize.intValue()); + new LoadRecentBranchRevisions( + myMergeContext.getBranchName(), dialog.getLastNumber(), myMergeContext.getWcInfo(), myMergeContext.getVcs(), + myMergeContext.getSourceUrl(), bunchSize.intValue()); final TaskDescriptor updater = new TaskDescriptor("", Where.AWT) { @Override public void run(ContinuationContext context) { @@ -231,7 +223,7 @@ public class QuickMerge { dialog.setEverythingLoaded(true); } }; - final Continuation fragmented = Continuation.createFragmented(myProject, true); + final Continuation fragmented = Continuation.createFragmented(myMergeContext.getProject(), true); fragmented.addExceptionHandler(VcsException.class, new Consumer() { @Override public void consume(VcsException e) { @@ -242,7 +234,8 @@ public class QuickMerge { } }; final List lists = myInteraction.showRecentListsForSelection(myLoader.getCommittedChangeLists(), - myTitle, myLoader.getHelper(), loader, myLoader.isLastLoaded()); + myMergeContext.getTitle(), myLoader.getHelper(), + loader, myLoader.isLastLoaded()); if (lists != null && ! lists.isEmpty()){ final MergerFactory factory = new ChangeListsMergerFactory(lists) { @@ -253,10 +246,10 @@ public class QuickMerge { }; // fictive branch point, just for final SvnBranchPointsCalculator.BranchCopyData copyData = - new SvnBranchPointsCalculator.BranchCopyData(myWcInfo.getUrl().toString(), -1, mySourceUrl, -1); - context.next(new LocalChangesPrompt(false, lists, - new SvnBranchPointsCalculator.WrapperInvertor(false, copyData)), - new MergeTask(factory, myTitle)); + new SvnBranchPointsCalculator.BranchCopyData(myMergeContext.getWcInfo().getUrl().toString(), -1, myMergeContext.getSourceUrl(), + -1); + context.next(new LocalChangesPrompt(false, lists, new SvnBranchPointsCalculator.WrapperInvertor(false, copyData)), + new MergeTask(factory, myMergeContext.getTitle())); } else { context.cancelEverything(); } @@ -277,7 +270,9 @@ public class QuickMerge { return; } if (QuickMergeContentsVariants.showLatest == variant) { - final LoadRecentBranchRevisions loader = new LoadRecentBranchRevisions(myBranchName, -1, myWcInfo, myVcs, mySourceUrl); + final LoadRecentBranchRevisions loader = + new LoadRecentBranchRevisions(myMergeContext.getBranchName(), -1, myMergeContext.getWcInfo(), myMergeContext + .getVcs(), myMergeContext.getSourceUrl()); final ShowRecentInDialog dialog = new ShowRecentInDialog(loader); context.next(loader, dialog); return; @@ -285,14 +280,15 @@ public class QuickMerge { final MergeCalculator calculator; try { - calculator = new MergeCalculator(myWcInfo, mySourceUrl, myBranchName); + calculator = new MergeCalculator(myMergeContext.getWcInfo(), myMergeContext.getSourceUrl(), myMergeContext.getBranchName()); } catch (VcsException e) { finishWithError(context, e.getMessage(), true); return; } - context.next(myVcs.getSvnBranchPointsCalculator().getFirstCopyPointTask( - myWcInfo.getRepositoryRoot(), myWcInfo.getRootUrl(), mySourceUrl, calculator), calculator); + context.next(myMergeContext.getVcs().getSvnBranchPointsCalculator() + .getFirstCopyPointTask(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getWcInfo().getRootUrl(), + myMergeContext.getSourceUrl(), calculator), calculator); } } @@ -303,10 +299,10 @@ public class QuickMerge { } private boolean checkForSwitchedRoots() { - final List infoList = myVcs.getAllWcInfos(); + final List infoList = myMergeContext.getVcs().getAllWcInfos(); boolean switchedFound = false; for (WCInfo wcInfo : infoList) { - if (FileUtil.isAncestor(new File(myWcInfo.getPath()), new File(wcInfo.getPath()), true) + if (FileUtil.isAncestor(new File(myMergeContext.getWcInfo().getPath()), new File(wcInfo.getPath()), true) && NestedCopyType.switched.equals(wcInfo.getType())) { switchedFound = true; break; @@ -349,7 +345,9 @@ public class QuickMerge { private void insertMergeAll(final List queue) { queue.add(new LocalChangesPrompt(true, null, null)); final MergeAllWithBranchCopyPoint mergeAllExecutor = new MergeAllWithBranchCopyPoint(); - queue.add(myVcs.getSvnBranchPointsCalculator().getFirstCopyPointTask(myWcInfo.getRepositoryRoot(), mySourceUrl, myWcInfo.getRootUrl(), mergeAllExecutor)); + queue.add(myMergeContext.getVcs().getSvnBranchPointsCalculator() + .getFirstCopyPointTask(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl(), + myMergeContext.getWcInfo().getRootUrl(), mergeAllExecutor)); queue.add(mergeAllExecutor); } @@ -387,13 +385,13 @@ public class QuickMerge { return; } final boolean reintegrate = invertor.isInvertedSense(); - if (reintegrate && (! myInteraction.shouldReintegrate(mySourceUrl, invertor.inverted().getTarget()))) { + if (reintegrate && (!myInteraction.shouldReintegrate(myMergeContext.getSourceUrl(), invertor.inverted().getTarget()))) { context.cancelEverything(); return; } final MergerFactory mergerFactory = createBranchMergerFactory(reintegrate, invertor); - final String title = "Merging all from " + myBranchName + (reintegrate ? " (reintegrate)" : ""); + final String title = "Merging all from " + myMergeContext.getBranchName() + (reintegrate ? " (reintegrate)" : ""); context.next(new MergeTask(mergerFactory, title)); } @@ -401,7 +399,8 @@ public class QuickMerge { final SvnBranchPointsCalculator.WrapperInvertor invertor) { return new MergerFactory() { public IMerger createMerger(SvnVcs vcs, File target, UpdateEventHandler handler, SVNURL currentBranchUrl, String branchName) { - return new BranchMerger(vcs, currentBranchUrl, myWcInfo.getUrl(), myWcInfo.getPath(), handler, reintegrate, myBranchName, + return new BranchMerger(vcs, currentBranchUrl, myMergeContext.getWcInfo().getUrl(), myMergeContext.getWcInfo().getPath(), handler, + reintegrate, myMergeContext.getBranchName(), reintegrate ? invertor.getWrapped().getTargetRevision() : invertor.getWrapped().getSourceRevision()); } }; @@ -421,14 +420,16 @@ public class QuickMerge { public void run(ContinuationContext context) { final SVNURL sourceUrlUrl; try { - sourceUrlUrl = SVNURL.parseURIEncoded(mySourceUrl); + sourceUrlUrl = SVNURL.parseURIEncoded(myMergeContext.getSourceUrl()); } catch (SVNException e) { finishWithError(context, "Cannot merge: " + e.getMessage(), true); return; } - final SvnIntegrateChangesTask task = new SvnIntegrateChangesTask(SvnVcs.getInstance(myProject), - new WorkingCopyInfo(myWcInfo.getPath(), true), myFactory, sourceUrlUrl, getName(), false, myBranchName); + final SvnIntegrateChangesTask task = new SvnIntegrateChangesTask(myMergeContext.getVcs(), + new WorkingCopyInfo(myMergeContext.getWcInfo().getPath(), true), + myFactory, sourceUrlUrl, getName(), false, + myMergeContext.getBranchName()); final TaskDescriptor taskDescriptor = TaskDescriptor.createForBackgroundableTask(task); // merge task will be the next after... context.next(taskDescriptor); @@ -437,8 +438,8 @@ public class QuickMerge { } private void createChangelist(final ContinuationPause context) { - final ChangeListManager listManager = ChangeListManager.getInstance(myProject); - String name = myTitle; + final ChangeListManager listManager = ChangeListManager.getInstance(myMergeContext.getProject()); + String name = myMergeContext.getTitle(); int i = 1; boolean updateDefaultList = false; while (true) { @@ -456,7 +457,7 @@ public class QuickMerge { } break; } - name = myTitle + " (" + i + ")"; + name = myMergeContext.getTitle() + " (" + i + ")"; ++ i; } if (updateDefaultList) { @@ -559,8 +560,8 @@ public class QuickMerge { myNotMerged = new LinkedList(); myMergeTitle = "Merge from " + branchName; // if (Boolean.TRUE.equals(Boolean.getBoolean(ourOneShotStrategy))) { - myMergeChecker = new OneShotMergeInfoHelper(myProject, myWcInfo, mySourceUrl); - ((OneShotMergeInfoHelper) myMergeChecker).prepare(); + myMergeChecker = new OneShotMergeInfoHelper(myMergeContext.getProject(), myWcInfo, mySourceUrl); + ((OneShotMergeInfoHelper)myMergeChecker).prepare(); /* } else { myMergeChecker = new BranchInfo.MyMergeCheckerWrapper(myWcInfo.getPath(), new BranchInfo(myVcs, myWcInfo.getRepositoryRoot(), myWcInfo.getRootUrl(), mySourceUrl, @@ -591,7 +592,8 @@ public class QuickMerge { final SvnBranchPointsCalculator.BranchCopyData data = copyDataValue.getTrue(); final long sourceLatest = data.getTargetRevision(); - final SvnCommittedChangesProvider committedChangesProvider = (SvnCommittedChangesProvider)myVcs.getCommittedChangesProvider(); + final SvnCommittedChangesProvider committedChangesProvider = + (SvnCommittedChangesProvider)myMergeContext.getVcs().getCommittedChangesProvider(); final ChangeBrowserSettings settings = new ChangeBrowserSettings(); settings.CHANGE_AFTER = Long.toString(sourceLatest); settings.USE_CHANGE_AFTER_FILTER = true; @@ -690,19 +692,19 @@ public class QuickMerge { @Nullable private File getLocalPath(final String relativeToRepoPath) { // from source if not inverted - final String pathToCheck = SVNPathUtil.append(myWcInfo.getRepositoryRoot(), relativeToRepoPath); + final String pathToCheck = SVNPathUtil.append(myMergeContext.getWcInfo().getRepositoryRoot(), relativeToRepoPath); final SvnBranchPointsCalculator.BranchCopyData wrapped = myCopyPoint.getWrapped(); final String relativeInSource = SVNPathUtil.getRelativePath(myCopyPoint.isInvertedSense() ? wrapped.getSource() : wrapped.getTarget(), pathToCheck); if (StringUtil.isEmptyOrSpaces(relativeInSource)) return null; - final File local = new File(myWcInfo.getPath(), relativeInSource); + final File local = new File(myMergeContext.getWcInfo().getPath(), relativeInSource); return local; } @Override public void run(ContinuationContext context) { final Intersection intersection; - final ChangeListManager listManager = ChangeListManager.getInstance(myProject); + final ChangeListManager listManager = ChangeListManager.getInstance(myMergeContext.getProject()); final List localChangeLists = listManager.getChangeListsCopy(); if (myMergeAll) { @@ -801,8 +803,10 @@ public class QuickMerge { FileDocumentManager.getInstance().saveAllDocuments(); } }, ModalityState.NON_MODAL); - ShelveChangesManager.getInstance(myProject).shelveChanges(changes, myIntersection.getComment(name) + " (auto shelve before merge)", - true); + ShelveChangesManager.getInstance(myMergeContext.getProject()).shelveChanges(changes, myIntersection.getComment(name) + + " (auto shelve before merge)", + true + ); session.addAllFiles(ChangesUtil.getFilesFromChanges(changes)); } catch (IOException e) { diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java index bc1d2cd4fd25..d1d1f58a2e63 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnQuickMergeTest.java @@ -37,10 +37,7 @@ import org.jetbrains.idea.SvnTestCase; import org.jetbrains.idea.svn.branchConfig.InfoReliability; import org.jetbrains.idea.svn.branchConfig.InfoStorage; import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew; -import org.jetbrains.idea.svn.dialogs.MergeDialogI; -import org.jetbrains.idea.svn.dialogs.QuickMerge; -import org.jetbrains.idea.svn.dialogs.QuickMergeContentsVariants; -import org.jetbrains.idea.svn.dialogs.WCInfo; +import org.jetbrains.idea.svn.dialogs.*; import org.jetbrains.idea.svn.integrate.SvnBranchItem; import org.jetbrains.idea.svn.mergeinfo.MergeChecker; import org.junit.Before; @@ -107,9 +104,7 @@ public class SvnQuickMergeTest extends Svn17TestCase { VcsTestUtil.editFileInCommand(myProject, myBranchTree.myS1File, "edited in branch"); runInAndVerifyIgnoreOutput(myBranchRoot, "ci", "-m", "change in branch", myBranchTree.myS1File.getPath()); - final WCInfo found = getWcInfo(); - final QuickMerge quickMerge = - new QuickMerge(myProject, myBranchUrl, found, SVNPathUtil.tail(myBranchUrl), myWorkingCopyDir); + final QuickMerge quickMerge = newQuickMerge(myBranchUrl); // by default merges all final QuickMergeTestInteraction testInteraction = new QuickMergeTestInteraction() { @Override @@ -174,9 +169,7 @@ public class SvnQuickMergeTest extends Svn17TestCase { } // we should get exactly 2 revisions for selection (copy and change in b2) - final WCInfo found = getWcInfo(); - final QuickMerge quickMerge = - new QuickMerge(myProject, myBranchUrl, found, SVNPathUtil.tail(myBranchUrl), myWorkingCopyDir); + final QuickMerge quickMerge = newQuickMerge(myBranchUrl); // by default merges all final AtomicReference selectionError = new AtomicReference(); final QuickMergeTestInteraction testInteraction = new QuickMergeTestInteraction() { @@ -268,9 +261,7 @@ public class SvnQuickMergeTest extends Svn17TestCase { runInAndVerifyIgnoreOutput(myBranchRoot, "ci", "-m", "change in b2", myBranchTree.myS2File.getPath()); // we should get exactly 2 revisions for selection (copy and change in b2) - final WCInfo found = getWcInfo(); - final QuickMerge quickMerge = - new QuickMerge(myProject, myRepoUrl + "/branches/b2", found, SVNPathUtil.tail(myRepoUrl + "/branches/b2"), myWorkingCopyDir); + final QuickMerge quickMerge = newQuickMerge(myRepoUrl + "/branches/b2"); // by default merges all final AtomicReference selectionError = new AtomicReference(); final QuickMergeTestInteraction testInteraction = new QuickMergeTestInteraction() { @@ -344,9 +335,7 @@ public class SvnQuickMergeTest extends Svn17TestCase { Thread.sleep(10); } - final WCInfo found = getWcInfo(); - final QuickMerge quickMerge = - new QuickMerge(myProject, myBranchUrl, found, SVNPathUtil.tail(myBranchUrl), myWorkingCopyDir); + final QuickMerge quickMerge = newQuickMerge(myBranchUrl); // by default merges all final QuickMergeTestInteraction testInteraction = new QuickMergeTestInteraction() { @Override @@ -436,9 +425,7 @@ public class SvnQuickMergeTest extends Svn17TestCase { myTree = new SubTree(myWorkingCopyDir); //reload refreshSvnMappingsSynchronously(); - final WCInfo found = getWcInfo(); - final QuickMerge quickMerge = - new QuickMerge(myProject, trunkUrl, found, SVNPathUtil.tail(trunkUrl), myWorkingCopyDir); + final QuickMerge quickMerge = newQuickMerge(trunkUrl); // by default merges all final QuickMergeTestInteraction testInteraction = new QuickMergeTestInteraction(); final WaitingTaskDescriptor descriptor = new WaitingTaskDescriptor(); @@ -466,6 +453,12 @@ public class SvnQuickMergeTest extends Svn17TestCase { Assert.assertEquals(FileStatus.MODIFIED, dirChange.getFileStatus()); } + private QuickMerge newQuickMerge(@NotNull String sourceUrl) { + MergeContext mergeContext = new MergeContext(myVcs, sourceUrl, getWcInfo(), SVNPathUtil.tail(sourceUrl), myWorkingCopyDir); + + return new QuickMerge(mergeContext); + } + private static class WaitingTaskDescriptor extends TaskDescriptor { private static final long TEST_TIMEOUT = TimeUnit.MINUTES.toMillis(200); private final Semaphore mySemaphore; From cf3252c5c00321523a54705b7adcc0f6f200be94 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 18 Apr 2014 19:00:49 +0400 Subject: [PATCH 15/65] svn: Refactored QuickMerge - make task classes do not directly depend on QuickMerge instance * MergeContext and QuickMergeInteraction parameters added to all task constructors * several QuickMerge methods moved to corresponding task classes --- .../idea/svn/dialogs/QuickMerge.java | 256 ++++++++++-------- 1 file changed, 145 insertions(+), 111 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java index 36fae18f462f..f20d3a5f37ce 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java @@ -78,9 +78,67 @@ public class QuickMerge { myContinuation = Continuation.createFragmented(mergeContext.getProject(), true); } - private class SourceUrlCorrection extends TaskDescriptor { - private SourceUrlCorrection() { - super("Checking branch", Where.POOLED); + private static abstract class BaseMergeTask extends TaskDescriptor { + + @NotNull protected final MergeContext myMergeContext; + @NotNull protected final QuickMergeInteraction myInteraction; + + public BaseMergeTask(@NotNull MergeContext mergeContext, + @NotNull QuickMergeInteraction interaction, String name, + @NotNull Where where) { + super(name, where); + myMergeContext = mergeContext; + myInteraction = interaction; + } + + protected void insertMergeAll(final ContinuationContext context) { + final List queue = new ArrayList(); + insertMergeAll(queue); + context.next(queue); + } + + protected void insertMergeAll(final List queue) { + queue.add(new LocalChangesPrompt(myMergeContext, myInteraction, true, null, null)); + final MergeAllWithBranchCopyPoint mergeAllExecutor = new MergeAllWithBranchCopyPoint(myMergeContext, myInteraction); + queue.add(myMergeContext.getVcs().getSvnBranchPointsCalculator() + .getFirstCopyPointTask(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl(), + myMergeContext.getWcInfo().getRootUrl(), mergeAllExecutor)); + queue.add(mergeAllExecutor); + } + + @CalledInAny + protected void finishWithError(final ContinuationContext context, final String message, final boolean isError) { + LOG.info((isError ? "Error: " : "Info: ") + message); + context.next(new TaskDescriptor(message, Where.AWT) { + @Override + public void run(ContinuationContext context) { + myInteraction.showErrors(message, isError); + context.cancelEverything(); + } + }); + } + + @CalledInAny + protected void finishWithError(final ContinuationContext context, final String message, final List exceptions) { + if (exceptions != null) { + for (VcsException exception : exceptions) { + LOG.info(message, exception); + } + } + context.cancelEverything(); + context.next(new TaskDescriptor(message, Where.AWT) { + @Override + public void run(ContinuationContext context) { + myInteraction.showErrors(message, exceptions); + } + }); + } + } + + private static class SourceUrlCorrection extends BaseMergeTask { + + private SourceUrlCorrection(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { + super(mergeContext, interaction, "Checking branch", Where.POOLED); } @Override @@ -98,9 +156,10 @@ public class QuickMerge { } } - private class MyInitChecks extends TaskDescriptor { - private MyInitChecks() { - super("initial checks", Where.AWT); + private static class MyInitChecks extends BaseMergeTask { + + private MyInitChecks(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { + super(mergeContext, interaction, "initial checks", Where.AWT); } @Override @@ -121,6 +180,22 @@ public class QuickMerge { } } + private boolean checkForSwitchedRoots() { + final List infoList = myMergeContext.getVcs().getAllWcInfos(); + boolean switchedFound = false; + for (WCInfo wcInfo : infoList) { + if (FileUtil.isAncestor(new File(myMergeContext.getWcInfo().getPath()), new File(wcInfo.getPath()), true) + && NestedCopyType.switched.equals(wcInfo.getType())) { + switchedFound = true; + break; + } + } + if (switchedFound) { + return myInteraction.shouldContinueSwitchedRootFound(); + } + return true; + } + @Nullable private SVNURL parseUrl(ContinuationContext continuationContext) { SVNURL url = null; @@ -136,9 +211,10 @@ public class QuickMerge { } } - private class CheckRepositorySupportsMergeinfo extends TaskDescriptor { - private CheckRepositorySupportsMergeinfo() { - super("Checking repository capabilities", Where.POOLED); + private static class CheckRepositorySupportsMergeinfo extends BaseMergeTask { + + private CheckRepositorySupportsMergeinfo(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { + super(mergeContext, interaction, "Checking repository capabilities", Where.POOLED); } @Override @@ -149,7 +225,7 @@ public class QuickMerge { if (! supportsMergeinfo) { insertMergeAll(tasks); } else { - tasks.add(new MergeAllOrSelectedChooser()); + tasks.add(new MergeAllOrSelectedChooser(myMergeContext, myInteraction)); } context.next(tasks); } @@ -163,9 +239,9 @@ public class QuickMerge { FileDocumentManager.getInstance().saveAllDocuments(); final List tasks = new LinkedList(); - tasks.add(new MyInitChecks()); - tasks.add(new SourceUrlCorrection()); - tasks.add(new CheckRepositorySupportsMergeinfo()); + tasks.add(new MyInitChecks(myMergeContext, myInteraction)); + tasks.add(new SourceUrlCorrection(myMergeContext, myInteraction)); + tasks.add(new CheckRepositorySupportsMergeinfo(myMergeContext, myInteraction)); if (finalTasks.length > 0) { tasks.addAll(Arrays.asList(finalTasks)); } @@ -191,11 +267,13 @@ public class QuickMerge { myContinuation.run(tasks); } - private class ShowRecentInDialog extends TaskDescriptor { + private static class ShowRecentInDialog extends BaseMergeTask { private final LoadRecentBranchRevisions myLoader; - private ShowRecentInDialog(LoadRecentBranchRevisions loader) { - super("", Where.AWT); + private ShowRecentInDialog(@NotNull MergeContext mergeContext, + @NotNull QuickMergeInteraction interaction, + LoadRecentBranchRevisions loader) { + super(mergeContext, interaction, "", Where.AWT); myLoader = loader; } @@ -248,17 +326,19 @@ public class QuickMerge { final SvnBranchPointsCalculator.BranchCopyData copyData = new SvnBranchPointsCalculator.BranchCopyData(myMergeContext.getWcInfo().getUrl().toString(), -1, myMergeContext.getSourceUrl(), -1); - context.next(new LocalChangesPrompt(false, lists, new SvnBranchPointsCalculator.WrapperInvertor(false, copyData)), - new MergeTask(factory, myMergeContext.getTitle())); + context.next(new LocalChangesPrompt(myMergeContext, myInteraction, + false, lists, new SvnBranchPointsCalculator.WrapperInvertor(false, copyData) + ), + new MergeTask(myMergeContext, myInteraction, factory, myMergeContext.getTitle())); } else { context.cancelEverything(); } } } - private class MergeAllOrSelectedChooser extends TaskDescriptor { - private MergeAllOrSelectedChooser() { - super("merge source selector", Where.AWT); + private static class MergeAllOrSelectedChooser extends BaseMergeTask { + private MergeAllOrSelectedChooser(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { + super(mergeContext, interaction, "merge source selector", Where.AWT); } @Override @@ -273,14 +353,15 @@ public class QuickMerge { final LoadRecentBranchRevisions loader = new LoadRecentBranchRevisions(myMergeContext.getBranchName(), -1, myMergeContext.getWcInfo(), myMergeContext .getVcs(), myMergeContext.getSourceUrl()); - final ShowRecentInDialog dialog = new ShowRecentInDialog(loader); + final ShowRecentInDialog dialog = new ShowRecentInDialog(myMergeContext, myInteraction, loader); context.next(loader, dialog); return; } final MergeCalculator calculator; try { - calculator = new MergeCalculator(myMergeContext.getWcInfo(), myMergeContext.getSourceUrl(), myMergeContext.getBranchName()); + calculator = new MergeCalculator(myMergeContext, myInteraction, myMergeContext.getWcInfo(), myMergeContext.getSourceUrl(), myMergeContext.getBranchName() + ); } catch (VcsException e) { finishWithError(context, e.getMessage(), true); @@ -292,70 +373,13 @@ public class QuickMerge { } } - private void insertMergeAll(final ContinuationContext context) { - final List queue = new ArrayList(); - insertMergeAll(queue); - context.next(queue); - } + private static class MergeAllWithBranchCopyPoint extends BaseMergeTask + implements Consumer> { - private boolean checkForSwitchedRoots() { - final List infoList = myMergeContext.getVcs().getAllWcInfos(); - boolean switchedFound = false; - for (WCInfo wcInfo : infoList) { - if (FileUtil.isAncestor(new File(myMergeContext.getWcInfo().getPath()), new File(wcInfo.getPath()), true) - && NestedCopyType.switched.equals(wcInfo.getType())) { - switchedFound = true; - break; - } - } - if (switchedFound) { - return myInteraction.shouldContinueSwitchedRootFound(); - } - return true; - } - - @CalledInAny - private void finishWithError(final ContinuationContext context, final String message, final List exceptions) { - if (exceptions != null) { - for (VcsException exception : exceptions) { - LOG.info(message, exception); - } - } - context.cancelEverything(); - context.next(new TaskDescriptor(message, Where.AWT) { - @Override - public void run(ContinuationContext context) { - myInteraction.showErrors(message, exceptions); - } - }); - } - - @CalledInAny - private void finishWithError(final ContinuationContext context, final String message, final boolean isError) { - LOG.info((isError ? "Error: " : "Info: ") + message); - context.next(new TaskDescriptor(message, Where.AWT) { - @Override - public void run(ContinuationContext context) { - myInteraction.showErrors(message, isError); - context.cancelEverything(); - } - }); - } - - private void insertMergeAll(final List queue) { - queue.add(new LocalChangesPrompt(true, null, null)); - final MergeAllWithBranchCopyPoint mergeAllExecutor = new MergeAllWithBranchCopyPoint(); - queue.add(myMergeContext.getVcs().getSvnBranchPointsCalculator() - .getFirstCopyPointTask(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl(), - myMergeContext.getWcInfo().getRootUrl(), mergeAllExecutor)); - queue.add(mergeAllExecutor); - } - - private class MergeAllWithBranchCopyPoint extends TaskDescriptor implements Consumer> { private final AtomicReference> myData; - private MergeAllWithBranchCopyPoint() { - super("merge all", Where.AWT); + private MergeAllWithBranchCopyPoint(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { + super(mergeContext, interaction, "merge all", Where.AWT); myData = new AtomicReference>(); } @@ -392,7 +416,7 @@ public class QuickMerge { final MergerFactory mergerFactory = createBranchMergerFactory(reintegrate, invertor); final String title = "Merging all from " + myMergeContext.getBranchName() + (reintegrate ? " (reintegrate)" : ""); - context.next(new MergeTask(mergerFactory, title)); + context.next(new MergeTask(myMergeContext, myInteraction, mergerFactory, title)); } private MergerFactory createBranchMergerFactory(final boolean reintegrate, @@ -407,12 +431,14 @@ public class QuickMerge { } } - private class MergeTask extends TaskDescriptor { + private static class MergeTask extends BaseMergeTask { private final MergerFactory myFactory; // awt since only a wrapper - private MergeTask(final MergerFactory factory, final String mergeTitle) { - super(mergeTitle, Where.AWT); + private MergeTask(@NotNull MergeContext mergeContext, + @NotNull QuickMergeInteraction interaction, final MergerFactory factory, + final String mergeTitle) { + super(mergeContext, interaction, mergeTitle, Where.AWT); myFactory = factory; } @@ -532,7 +558,7 @@ public class QuickMerge { return ! atLeastOneUnderBranch; } - private class MergeCalculator extends TaskDescriptor implements + private static class MergeCalculator extends BaseMergeTask implements Consumer> { private final static String ourOneShotStrategy = "svn.quickmerge.oneShotStrategy"; private final WCInfo myWcInfo; @@ -552,8 +578,11 @@ public class QuickMerge { myCopyData.set(value); } - private MergeCalculator(WCInfo wcInfo, String sourceUrl, String branchName) throws VcsException { - super("Calculating not merged revisions", Where.POOLED); + private MergeCalculator(@NotNull MergeContext mergeContext, + @NotNull QuickMergeInteraction interaction, WCInfo wcInfo, + String sourceUrl, + String branchName) throws VcsException { + super(mergeContext, interaction, "Calculating not merged revisions", Where.POOLED); myWcInfo = wcInfo; mySourceUrl = sourceUrl; myBranchName = branchName; @@ -669,26 +698,41 @@ public class QuickMerge { return new GroupMerger(vcs, lists, target, handler, currentBranchUrl, branchName, false, false, false); } }; - context.next(new LocalChangesPrompt(false, lists, myCopyPoint), new MergeTask(factory, myMergeTitle)); + context.next(new LocalChangesPrompt(myMergeContext, myInteraction, false, lists, myCopyPoint), new MergeTask(myMergeContext, + myInteraction, + factory, myMergeTitle + )); } } } } - private class LocalChangesPrompt extends TaskDescriptor { + private static class LocalChangesPrompt extends BaseMergeTask { private final boolean myMergeAll; @Nullable private final List myLists; private final SvnBranchPointsCalculator.WrapperInvertor myCopyPoint; - private LocalChangesPrompt(final boolean mergeAll, + private LocalChangesPrompt(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction, final boolean mergeAll, @Nullable final List lists, @Nullable SvnBranchPointsCalculator.WrapperInvertor copyPoint) { - super("local changes intersection check", Where.AWT); + super(mergeContext, interaction, "local changes intersection check", Where.AWT); myMergeAll = mergeAll; myLists = lists; myCopyPoint = copyPoint; } + private static Intersection getMergeAllIntersection(List localChangeLists) { + final Intersection intersection = new Intersection(); + + for (LocalChangeList localChangeList : localChangeLists) { + final Collection localChanges = localChangeList.getChanges(); + for (Change localChange : localChanges) { + intersection.add(localChangeList.getName(), localChangeList.getComment(), localChange); + } + } + return intersection; + } + @Nullable private File getLocalPath(final String relativeToRepoPath) { // from source if not inverted @@ -718,7 +762,7 @@ public class QuickMerge { switch (action) { // shelve case shelve: - context.next(new ShelveLocalChanges(intersection)); + context.next(new ShelveLocalChanges(myMergeContext, myInteraction, intersection)); return; // cancel case cancel: @@ -776,11 +820,13 @@ public class QuickMerge { } } - private class ShelveLocalChanges extends TaskDescriptor { + private static class ShelveLocalChanges extends BaseMergeTask { private final Intersection myIntersection; - private ShelveLocalChanges(final Intersection intersection) { - super("Shelving local changes before merge", Where.POOLED); + private ShelveLocalChanges(@NotNull MergeContext mergeContext, + @NotNull QuickMergeInteraction interaction, + final Intersection intersection) { + super(mergeContext, interaction, "Shelving local changes before merge", Where.POOLED); myIntersection = intersection; } @@ -822,18 +868,6 @@ public class QuickMerge { } } - private Intersection getMergeAllIntersection(List localChangeLists) { - final Intersection intersection = new Intersection(); - - for (LocalChangeList localChangeList : localChangeLists) { - final Collection localChanges = localChangeList.getChanges(); - for (Change localChange : localChanges) { - intersection.add(localChangeList.getName(), localChangeList.getComment(), localChange); - } - } - return intersection; - } - private static class Intersection { private final Map myLists; private final MultiMap myChangesSubset; From c85e79d6e5c9a059b5b6992716d1d73794cdcb0a Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 21 Apr 2014 16:13:59 +0400 Subject: [PATCH 16/65] svn: Refactored QuickMerge - inner classes moved to separate files (and renamed) --- .../dialogs/LoadRecentBranchRevisions.java | 6 +- .../idea/svn/dialogs/QuickMerge.java | 842 +----------------- .../idea/svn/integrate/BaseMergeTask.java | 90 ++ .../CheckRepositorySupportsMergeInfoTask.java | 50 ++ .../idea/svn/integrate/Intersection.java | 51 ++ .../svn/integrate/LocalChangesPromptTask.java | 155 ++++ .../MergeAllOrSelectedChooserTask.java | 65 ++ .../MergeAllWithBranchCopyPointTask.java | 94 ++ .../svn/integrate/MergeCalculatorTask.java | 275 ++++++ .../svn/integrate/MergeInitChecksTask.java | 90 ++ .../idea/svn/integrate/MergeTask.java | 99 ++ .../svn/integrate/ShelveLocalChangesTask.java | 84 ++ .../svn/integrate/ShowRecentInDialogTask.java | 114 +++ .../integrate/SourceUrlCorrectionTask.java | 48 + 14 files changed, 1233 insertions(+), 830 deletions(-) create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/BaseMergeTask.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/CheckRepositorySupportsMergeInfoTask.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Intersection.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/LocalChangesPromptTask.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllWithBranchCopyPointTask.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeInitChecksTask.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeTask.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShelveLocalChangesTask.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShowRecentInDialogTask.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java index 6591d9872ca8..3d77b5da426b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java @@ -45,7 +45,7 @@ import java.util.List; * Date: 3/30/13 * Time: 7:40 PM */ -class LoadRecentBranchRevisions extends TaskDescriptor { +public class LoadRecentBranchRevisions extends TaskDescriptor { public static final String PROP_BUNCH_SIZE = "idea.svn.quick.merge.bunch.size"; private final static int BUNCH_SIZE = 100; private int myBunchSize; @@ -58,11 +58,11 @@ class LoadRecentBranchRevisions extends TaskDescriptor { private final String mySourceUrl; private final Integer myTestBunchSize; - LoadRecentBranchRevisions(String branchName, long first, WCInfo info, SvnVcs vcs, String url) { + public LoadRecentBranchRevisions(String branchName, long first, WCInfo info, SvnVcs vcs, String url) { this(branchName, first, info, vcs, url, -1); } - LoadRecentBranchRevisions(String branchName, long first, WCInfo info, SvnVcs vcs, String url, final int bunchSize) { + public LoadRecentBranchRevisions(String branchName, long first, WCInfo info, SvnVcs vcs, String url, final int bunchSize) { super("Loading recent " + branchName + " revisions", Where.POOLED); myFirst = first; myWcInfo = info; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java index f20d3a5f37ce..d699a3a53153 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java @@ -15,222 +15,35 @@ */ package org.jetbrains.idea.svn.dialogs; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressManager; -import com.intellij.openapi.ui.MessageType; -import com.intellij.openapi.ui.popup.util.PopupUtil; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vcs.*; -import com.intellij.openapi.vcs.changes.*; -import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager; -import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; -import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; -import com.intellij.openapi.vfs.newvfs.RefreshSessionImpl; +import com.intellij.openapi.vcs.CalledInAwt; +import com.intellij.openapi.vcs.VcsException; import com.intellij.util.Consumer; -import com.intellij.util.FilePathByPathComparator; -import com.intellij.util.PairConsumer; -import com.intellij.util.containers.MultiMap; -import com.intellij.util.continuation.*; +import com.intellij.util.continuation.Continuation; +import com.intellij.util.continuation.TaskDescriptor; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.NestedCopyType; -import org.jetbrains.idea.svn.SvnBranchConfigurationManager; -import org.jetbrains.idea.svn.SvnUtil; -import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.actions.ChangeListsMergerFactory; -import org.jetbrains.idea.svn.commandLine.SvnBindException; -import org.jetbrains.idea.svn.history.SvnChangeList; -import org.jetbrains.idea.svn.history.SvnCommittedChangesProvider; -import org.jetbrains.idea.svn.history.SvnRepositoryLocation; -import org.jetbrains.idea.svn.history.TreeStructureNode; -import org.jetbrains.idea.svn.integrate.*; -import org.jetbrains.idea.svn.mergeinfo.MergeChecker; -import org.jetbrains.idea.svn.mergeinfo.OneShotMergeInfoHelper; -import org.jetbrains.idea.svn.mergeinfo.SvnMergeInfoCache; -import org.jetbrains.idea.svn.update.UpdateEventHandler; +import org.jetbrains.idea.svn.integrate.CheckRepositorySupportsMergeInfoTask; +import org.jetbrains.idea.svn.integrate.MergeInitChecksTask; +import org.jetbrains.idea.svn.integrate.QuickMergeInteraction; +import org.jetbrains.idea.svn.integrate.SourceUrlCorrectionTask; import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNLogEntry; -import org.tmatesoft.svn.core.SVNLogEntryPath; -import org.tmatesoft.svn.core.SVNURL; -import org.tmatesoft.svn.core.internal.util.SVNPathUtil; -import org.tmatesoft.svn.core.internal.util.SVNURLUtil; -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.concurrent.atomic.AtomicReference; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; public class QuickMerge { @NotNull private final MergeContext myMergeContext; private final Continuation myContinuation; private QuickMergeInteraction myInteraction; - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.dialogs.QuickMerge"); public QuickMerge(@NotNull MergeContext mergeContext) { myMergeContext = mergeContext; myContinuation = Continuation.createFragmented(mergeContext.getProject(), true); } - private static abstract class BaseMergeTask extends TaskDescriptor { - - @NotNull protected final MergeContext myMergeContext; - @NotNull protected final QuickMergeInteraction myInteraction; - - public BaseMergeTask(@NotNull MergeContext mergeContext, - @NotNull QuickMergeInteraction interaction, String name, - @NotNull Where where) { - super(name, where); - myMergeContext = mergeContext; - myInteraction = interaction; - } - - protected void insertMergeAll(final ContinuationContext context) { - final List queue = new ArrayList(); - insertMergeAll(queue); - context.next(queue); - } - - protected void insertMergeAll(final List queue) { - queue.add(new LocalChangesPrompt(myMergeContext, myInteraction, true, null, null)); - final MergeAllWithBranchCopyPoint mergeAllExecutor = new MergeAllWithBranchCopyPoint(myMergeContext, myInteraction); - queue.add(myMergeContext.getVcs().getSvnBranchPointsCalculator() - .getFirstCopyPointTask(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl(), - myMergeContext.getWcInfo().getRootUrl(), mergeAllExecutor)); - queue.add(mergeAllExecutor); - } - - @CalledInAny - protected void finishWithError(final ContinuationContext context, final String message, final boolean isError) { - LOG.info((isError ? "Error: " : "Info: ") + message); - context.next(new TaskDescriptor(message, Where.AWT) { - @Override - public void run(ContinuationContext context) { - myInteraction.showErrors(message, isError); - context.cancelEverything(); - } - }); - } - - @CalledInAny - protected void finishWithError(final ContinuationContext context, final String message, final List exceptions) { - if (exceptions != null) { - for (VcsException exception : exceptions) { - LOG.info(message, exception); - } - } - context.cancelEverything(); - context.next(new TaskDescriptor(message, Where.AWT) { - @Override - public void run(ContinuationContext context) { - myInteraction.showErrors(message, exceptions); - } - }); - } - } - - private static class SourceUrlCorrection extends BaseMergeTask { - - private SourceUrlCorrection(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { - super(mergeContext, interaction, "Checking branch", Where.POOLED); - } - - @Override - public void run(ContinuationContext continuationContext) { - final SVNURL branch = - SvnBranchConfigurationManager.getInstance(myMergeContext.getProject()).getSvnBranchConfigManager().getWorkingBranchWithReload( - myMergeContext.getWcInfo().getUrl(), myMergeContext.getRoot()); - if (branch != null && (!myMergeContext.getWcInfo().getUrl().equals(branch))) { - final String branchString = branch.toString(); - if (SVNPathUtil.isAncestor(branchString, myMergeContext.getWcInfo().getRootUrl())) { - final String subPath = SVNPathUtil.getRelativePath(branchString, myMergeContext.getWcInfo().getRootUrl()); - myMergeContext.setSourceUrl(SVNPathUtil.append(myMergeContext.getSourceUrl(), subPath)); - } - } - } - } - - private static class MyInitChecks extends BaseMergeTask { - - private MyInitChecks(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { - super(mergeContext, interaction, "initial checks", Where.AWT); - } - - @Override - public void run(ContinuationContext continuationContext) { - SVNURL url = parseUrl(continuationContext); - if (url == null) { - return; - } - - if (SVNURLUtil.isAncestor(url, myMergeContext.getWcInfo().getUrl()) || - SVNURLUtil.isAncestor(myMergeContext.getWcInfo().getUrl(), url)) { - finishWithError(continuationContext, "Cannot merge from self", true); - return; - } - - if (! checkForSwitchedRoots()) { - continuationContext.cancelEverything(); - } - } - - private boolean checkForSwitchedRoots() { - final List infoList = myMergeContext.getVcs().getAllWcInfos(); - boolean switchedFound = false; - for (WCInfo wcInfo : infoList) { - if (FileUtil.isAncestor(new File(myMergeContext.getWcInfo().getPath()), new File(wcInfo.getPath()), true) - && NestedCopyType.switched.equals(wcInfo.getType())) { - switchedFound = true; - break; - } - } - if (switchedFound) { - return myInteraction.shouldContinueSwitchedRootFound(); - } - return true; - } - - @Nullable - private SVNURL parseUrl(ContinuationContext continuationContext) { - SVNURL url = null; - - try { - url = SvnUtil.createUrl(myMergeContext.getSourceUrl()); - } - catch (SvnBindException e) { - finishWithError(continuationContext, e.getMessage(), true); - } - - return url; - } - } - - private static class CheckRepositorySupportsMergeinfo extends BaseMergeTask { - - private CheckRepositorySupportsMergeinfo(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { - super(mergeContext, interaction, "Checking repository capabilities", Where.POOLED); - } - - @Override - public void run(ContinuationContext context) { - final List tasks = new LinkedList(); - final boolean supportsMergeinfo = myMergeContext.getWcInfo().getFormat().supportsMergeInfo() && SvnUtil.checkRepositoryVersion15( - myMergeContext.getVcs(), myMergeContext.getSourceUrl()); - if (! supportsMergeinfo) { - insertMergeAll(tasks); - } else { - tasks.add(new MergeAllOrSelectedChooser(myMergeContext, myInteraction)); - } - context.next(tasks); - } - } - @CalledInAwt public void execute(@NotNull final QuickMergeInteraction interaction, @NotNull final TaskDescriptor... finalTasks) { myInteraction = interaction; @@ -239,9 +52,9 @@ public class QuickMerge { FileDocumentManager.getInstance().saveAllDocuments(); final List tasks = new LinkedList(); - tasks.add(new MyInitChecks(myMergeContext, myInteraction)); - tasks.add(new SourceUrlCorrection(myMergeContext, myInteraction)); - tasks.add(new CheckRepositorySupportsMergeinfo(myMergeContext, myInteraction)); + tasks.add(new MergeInitChecksTask(myMergeContext, myInteraction)); + tasks.add(new SourceUrlCorrectionTask(myMergeContext, myInteraction)); + tasks.add(new CheckRepositorySupportsMergeInfoTask(myMergeContext, myInteraction)); if (finalTasks.length > 0) { tasks.addAll(Arrays.asList(finalTasks)); } @@ -266,629 +79,4 @@ public class QuickMerge { }); myContinuation.run(tasks); } - - private static class ShowRecentInDialog extends BaseMergeTask { - private final LoadRecentBranchRevisions myLoader; - - private ShowRecentInDialog(@NotNull MergeContext mergeContext, - @NotNull QuickMergeInteraction interaction, - LoadRecentBranchRevisions loader) { - super(mergeContext, interaction, "", Where.AWT); - myLoader = loader; - } - - @Override - public void run(ContinuationContext context) { - final PairConsumer loader = new PairConsumer() { - @Override - public void consume(Long bunchSize, final MergeDialogI dialog) { - final LoadRecentBranchRevisions loader = - new LoadRecentBranchRevisions( - myMergeContext.getBranchName(), dialog.getLastNumber(), myMergeContext.getWcInfo(), myMergeContext.getVcs(), - myMergeContext.getSourceUrl(), bunchSize.intValue()); - final TaskDescriptor updater = new TaskDescriptor("", Where.AWT) { - @Override - public void run(ContinuationContext context) { - dialog.addMoreLists(loader.getCommittedChangeLists()); - if (loader.isLastLoaded()) { - dialog.setEverythingLoaded(true); - } - } - - @Override - public void canceled() { - dialog.addMoreLists(Collections.emptyList()); - dialog.setEverythingLoaded(true); - } - }; - final Continuation fragmented = Continuation.createFragmented(myMergeContext.getProject(), true); - fragmented.addExceptionHandler(VcsException.class, new Consumer() { - @Override - public void consume(VcsException e) { - PopupUtil.showBalloonForActiveComponent(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), MessageType.ERROR); - } - }); - fragmented.run(loader, updater); - } - }; - final List lists = myInteraction.showRecentListsForSelection(myLoader.getCommittedChangeLists(), - myMergeContext.getTitle(), myLoader.getHelper(), - loader, myLoader.isLastLoaded()); - - if (lists != null && ! lists.isEmpty()){ - final MergerFactory factory = new ChangeListsMergerFactory(lists) { - @Override - public IMerger createMerger(SvnVcs vcs, File target, UpdateEventHandler handler, SVNURL currentBranchUrl, String branchName) { - return new GroupMerger(vcs, lists, target, handler, currentBranchUrl, branchName, false, false, false); - } - }; - // fictive branch point, just for - final SvnBranchPointsCalculator.BranchCopyData copyData = - new SvnBranchPointsCalculator.BranchCopyData(myMergeContext.getWcInfo().getUrl().toString(), -1, myMergeContext.getSourceUrl(), - -1); - context.next(new LocalChangesPrompt(myMergeContext, myInteraction, - false, lists, new SvnBranchPointsCalculator.WrapperInvertor(false, copyData) - ), - new MergeTask(myMergeContext, myInteraction, factory, myMergeContext.getTitle())); - } else { - context.cancelEverything(); - } - } - } - - private static class MergeAllOrSelectedChooser extends BaseMergeTask { - private MergeAllOrSelectedChooser(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { - super(mergeContext, interaction, "merge source selector", Where.AWT); - } - - @Override - public void run(final ContinuationContext context) { - final QuickMergeContentsVariants variant = myInteraction.selectMergeVariant(); - if (QuickMergeContentsVariants.cancel == variant) return; - if (QuickMergeContentsVariants.all == variant) { - insertMergeAll(context); - return; - } - if (QuickMergeContentsVariants.showLatest == variant) { - final LoadRecentBranchRevisions loader = - new LoadRecentBranchRevisions(myMergeContext.getBranchName(), -1, myMergeContext.getWcInfo(), myMergeContext - .getVcs(), myMergeContext.getSourceUrl()); - final ShowRecentInDialog dialog = new ShowRecentInDialog(myMergeContext, myInteraction, loader); - context.next(loader, dialog); - return; - } - - final MergeCalculator calculator; - try { - calculator = new MergeCalculator(myMergeContext, myInteraction, myMergeContext.getWcInfo(), myMergeContext.getSourceUrl(), myMergeContext.getBranchName() - ); - } - catch (VcsException e) { - finishWithError(context, e.getMessage(), true); - return; - } - context.next(myMergeContext.getVcs().getSvnBranchPointsCalculator() - .getFirstCopyPointTask(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getWcInfo().getRootUrl(), - myMergeContext.getSourceUrl(), calculator), calculator); - } - } - - private static class MergeAllWithBranchCopyPoint extends BaseMergeTask - implements Consumer> { - - private final AtomicReference> myData; - - private MergeAllWithBranchCopyPoint(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { - super(mergeContext, interaction, "merge all", Where.AWT); - myData = new AtomicReference>(); - } - - @Override - public void consume(TransparentlyFailedValueI value) { - myData.set(value); - } - - @Override - public void run(ContinuationContext context) { - SvnBranchPointsCalculator.WrapperInvertor invertor; - try { - final TransparentlyFailedValueI - transparentlyFailedValueI = myData.get(); - if (transparentlyFailedValueI == null) { - finishWithError(context, "Merge start wasn't found", true); - return; - } - invertor = transparentlyFailedValueI.get(); - } - catch (VcsException e) { - finishWithError(context, "Merge start wasn't found", Collections.singletonList(e)); - return; - } - if (invertor == null) { - finishWithError(context, "Merge start wasn't found", true); - return; - } - final boolean reintegrate = invertor.isInvertedSense(); - if (reintegrate && (!myInteraction.shouldReintegrate(myMergeContext.getSourceUrl(), invertor.inverted().getTarget()))) { - context.cancelEverything(); - return; - } - final MergerFactory mergerFactory = createBranchMergerFactory(reintegrate, invertor); - - final String title = "Merging all from " + myMergeContext.getBranchName() + (reintegrate ? " (reintegrate)" : ""); - context.next(new MergeTask(myMergeContext, myInteraction, mergerFactory, title)); - } - - private MergerFactory createBranchMergerFactory(final boolean reintegrate, - final SvnBranchPointsCalculator.WrapperInvertor invertor) { - return new MergerFactory() { - public IMerger createMerger(SvnVcs vcs, File target, UpdateEventHandler handler, SVNURL currentBranchUrl, String branchName) { - return new BranchMerger(vcs, currentBranchUrl, myMergeContext.getWcInfo().getUrl(), myMergeContext.getWcInfo().getPath(), handler, - reintegrate, myMergeContext.getBranchName(), - reintegrate ? invertor.getWrapped().getTargetRevision() : invertor.getWrapped().getSourceRevision()); - } - }; - } - } - - private static class MergeTask extends BaseMergeTask { - private final MergerFactory myFactory; - - // awt since only a wrapper - private MergeTask(@NotNull MergeContext mergeContext, - @NotNull QuickMergeInteraction interaction, final MergerFactory factory, - final String mergeTitle) { - super(mergeContext, interaction, mergeTitle, Where.AWT); - myFactory = factory; - } - - @Override - public void run(ContinuationContext context) { - final SVNURL sourceUrlUrl; - try { - sourceUrlUrl = SVNURL.parseURIEncoded(myMergeContext.getSourceUrl()); - } catch (SVNException e) { - finishWithError(context, "Cannot merge: " + e.getMessage(), true); - return; - } - - final SvnIntegrateChangesTask task = new SvnIntegrateChangesTask(myMergeContext.getVcs(), - new WorkingCopyInfo(myMergeContext.getWcInfo().getPath(), true), - myFactory, sourceUrlUrl, getName(), false, - myMergeContext.getBranchName()); - final TaskDescriptor taskDescriptor = TaskDescriptor.createForBackgroundableTask(task); - // merge task will be the next after... - context.next(taskDescriptor); - // ... after we create changelist - createChangelist(context); - } - - private void createChangelist(final ContinuationPause context) { - final ChangeListManager listManager = ChangeListManager.getInstance(myMergeContext.getProject()); - String name = myMergeContext.getTitle(); - int i = 1; - boolean updateDefaultList = false; - while (true) { - final LocalChangeList changeList = listManager.findChangeList(name); - if (changeList == null) { - final LocalChangeList newList = listManager.addChangeList(name, null); - listManager.setDefaultChangeList(newList); - updateDefaultList = true; - break; - } - if (changeList.getChanges().isEmpty()) { - if (! changeList.isDefault()) { - listManager.setDefaultChangeList(changeList); - updateDefaultList = true; - } - break; - } - name = myMergeContext.getTitle() + " (" + i + ")"; - ++ i; - } - if (updateDefaultList) { - context.suspend(); - listManager.invokeAfterUpdate(new Runnable() { - public void run() { - context.ping(); - } - }, InvokeAfterUpdateMode.BACKGROUND_NOT_CANCELLABLE_NOT_AWT, "", ModalityState.NON_MODAL); - } - } - } - - // true if errors found - static boolean checkListForPaths(String relativeLocal, - String relativeBranch, Pair> pair) { - // TODO: Such filtering logic is not clear enough so far (and probably not correct for all cases - for instance when we perform merge - // TODO: from branch1 to branch2 and have revision which contain merge changes from branch3 to branch1. - // TODO: In this case paths of child log entries will not contain neither urls from branch1 nor from branch2 - and checkEntry() method - // TODO: will return true => so such revision will not be used (and displayed) further. - - // TODO: Why do we check entries recursively - we have a revision - set of changes in the "merge from" branch? Why do we need to check - // TODO: where they came from - we want avoid some circular merges or what? Does subversion itself perform such checks or not? - final List> children = pair.getSecond().getChildren(); - boolean localChange = false; - for (TreeStructureNode child : children) { - if (checkForSubtree(child, relativeLocal, relativeBranch)) { - localChange = true; - break; - } - } - if (! localChange) { - // check self - return checkForEntry(pair.getSecond().getMe(), relativeLocal, relativeBranch); - } - return localChange; - } - - // true if errors found - private static boolean checkForSubtree(final TreeStructureNode tree, - String relativeBranch, final String localURL) { - final LinkedList> queue = new LinkedList>(); - queue.addLast(tree); - - while (! queue.isEmpty()) { - final TreeStructureNode element = queue.removeFirst(); - ProgressManager.checkCanceled(); - - if (checkForEntry(element.getMe(), localURL, relativeBranch)) return true; - queue.addAll(element.getChildren()); - } - return false; - } - - // true if errors found - // checks if either some changed path is in current branch => treat as local change - // or if no changed paths in current branch, checks if at least one path in "merge from" branch - // NOTE: this fails for "merge-source" log entries from other branches - when all changed paths are from some - // third branch - this logic treats such log entry as local. - private static boolean checkForEntry(final SVNLogEntry entry, final String localURL, String relativeBranch) { - boolean atLeastOneUnderBranch = false; - final Map map = entry.getChangedPaths(); - for (Object o : map.values()) { - final SVNLogEntryPath path = (SVNLogEntryPath) o; - if (SVNPathUtil.isAncestor(localURL, path.getPath())) { - return true; - } - if (! atLeastOneUnderBranch && SVNPathUtil.isAncestor(relativeBranch, path.getPath())) { - atLeastOneUnderBranch = true; - } - } - return ! atLeastOneUnderBranch; - } - - private static class MergeCalculator extends BaseMergeTask implements - Consumer> { - private final static String ourOneShotStrategy = "svn.quickmerge.oneShotStrategy"; - private final WCInfo myWcInfo; - private final String mySourceUrl; - private final String myBranchName; - private final - AtomicReference> - myCopyData; - private boolean myIsReintegrate; - - private final List myNotMerged; - private String myMergeTitle; - private final MergeChecker myMergeChecker; - - @Override - public void consume(TransparentlyFailedValueI value) { - myCopyData.set(value); - } - - private MergeCalculator(@NotNull MergeContext mergeContext, - @NotNull QuickMergeInteraction interaction, WCInfo wcInfo, - String sourceUrl, - String branchName) throws VcsException { - super(mergeContext, interaction, "Calculating not merged revisions", Where.POOLED); - myWcInfo = wcInfo; - mySourceUrl = sourceUrl; - myBranchName = branchName; - myNotMerged = new LinkedList(); - myMergeTitle = "Merge from " + branchName; -// if (Boolean.TRUE.equals(Boolean.getBoolean(ourOneShotStrategy))) { - myMergeChecker = new OneShotMergeInfoHelper(myMergeContext.getProject(), myWcInfo, mySourceUrl); - ((OneShotMergeInfoHelper)myMergeChecker).prepare(); -/* } else { - myMergeChecker = new BranchInfo.MyMergeCheckerWrapper(myWcInfo.getPath(), new BranchInfo(myVcs, myWcInfo.getRepositoryRoot(), - myWcInfo.getRootUrl(), mySourceUrl, - mySourceUrl, myVcs.createWCClient())); - }*/ - myCopyData = new AtomicReference>(); - } - - //"Calculating not merged revisions" - @Override - public void run(ContinuationContext context) { - SvnBranchPointsCalculator.WrapperInvertor copyDataValue = null; - try { - copyDataValue = myCopyData.get().get(); - } - catch (VcsException e) { - finishWithError(context, "Merge start wasn't found", Collections.singletonList(e)); - return; - } - if (copyDataValue == null) { - finishWithError(context, "Merge start wasn't found", true); - return; - } - - final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); - myIsReintegrate = copyDataValue.isInvertedSense(); - if (!myWcInfo.getFormat().supportsMergeInfo()) return; - final SvnBranchPointsCalculator.BranchCopyData data = copyDataValue.getTrue(); - final long sourceLatest = data.getTargetRevision(); - - final SvnCommittedChangesProvider committedChangesProvider = - (SvnCommittedChangesProvider)myMergeContext.getVcs().getCommittedChangesProvider(); - final ChangeBrowserSettings settings = new ChangeBrowserSettings(); - settings.CHANGE_AFTER = Long.toString(sourceLatest); - settings.USE_CHANGE_AFTER_FILTER = true; - - String local = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), myWcInfo.getRootUrl()); - final String relativeLocal = (local.startsWith("/") ? local : "/" + local); - String relativeBranch = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), mySourceUrl); - relativeBranch = (relativeBranch.startsWith("/") ? relativeBranch : "/" + relativeBranch); - - final LinkedList>> list = - new LinkedList>>(); - try { - committedChangesProvider.getCommittedChangesWithMergedRevisons(settings, new SvnRepositoryLocation(mySourceUrl), 0, - new PairConsumer>() { - public void consume(SvnChangeList svnList, TreeStructureNode tree) { - indicator.checkCanceled(); - if (sourceLatest >= svnList.getNumber()) return; - list.add(new Pair>(svnList, tree)); - } - }); - } - catch (VcsException e) { - finishWithError(context, "Checking revisions for merge fault", Collections.singletonList(e)); - } - - indicator.setText("Checking merge information..."); - // to do not go into file system while asking something on the net - for (Pair> pair : list) { - final SvnChangeList svnList = pair.getFirst(); - final SvnMergeInfoCache.MergeCheckResult checkResult = myMergeChecker.checkList(svnList); - indicator.setText2("Processing revision " + svnList.getNumber()); - - if (SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(checkResult)) { - // additionally check for being 'local' - boolean localChange = checkListForPaths(relativeLocal, relativeBranch, pair); - - if (! localChange) { - myNotMerged.add(svnList); - } - } - } - - if (myNotMerged.isEmpty()) { - finishWithError(context, "Everything is up-to-date", false); - return; - } - context.next(new ShowRevisionSelector(copyDataValue)); - } - - private class ShowRevisionSelector extends TaskDescriptor { - private final SvnBranchPointsCalculator.WrapperInvertor myCopyPoint; - - private ShowRevisionSelector(SvnBranchPointsCalculator.WrapperInvertor copyPoint) { - super("show revisions to merge", Where.AWT); - myCopyPoint = copyPoint; - } - - @Override - public void run(ContinuationContext context) { - final QuickMergeInteraction.SelectMergeItemsResult result = myInteraction.selectMergeItems(myNotMerged, myMergeTitle, myMergeChecker); - if (QuickMergeContentsVariants.cancel == result.getResultCode()) { - context.cancelEverything(); - return; - } - if (QuickMergeContentsVariants.all == result.getResultCode()) { - insertMergeAll(context); - } else { - final List lists = result.getSelectedLists(); - if (lists.isEmpty()) return; - final MergerFactory factory = new ChangeListsMergerFactory(lists) { - @Override - public IMerger createMerger(SvnVcs vcs, File target, UpdateEventHandler handler, SVNURL currentBranchUrl, String branchName) { - return new GroupMerger(vcs, lists, target, handler, currentBranchUrl, branchName, false, false, false); - } - }; - context.next(new LocalChangesPrompt(myMergeContext, myInteraction, false, lists, myCopyPoint), new MergeTask(myMergeContext, - myInteraction, - factory, myMergeTitle - )); - } - } - } - } - - private static class LocalChangesPrompt extends BaseMergeTask { - private final boolean myMergeAll; - @Nullable private final List myLists; - private final SvnBranchPointsCalculator.WrapperInvertor myCopyPoint; - - private LocalChangesPrompt(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction, final boolean mergeAll, - @Nullable final List lists, - @Nullable SvnBranchPointsCalculator.WrapperInvertor copyPoint) { - super(mergeContext, interaction, "local changes intersection check", Where.AWT); - myMergeAll = mergeAll; - myLists = lists; - myCopyPoint = copyPoint; - } - - private static Intersection getMergeAllIntersection(List localChangeLists) { - final Intersection intersection = new Intersection(); - - for (LocalChangeList localChangeList : localChangeLists) { - final Collection localChanges = localChangeList.getChanges(); - for (Change localChange : localChanges) { - intersection.add(localChangeList.getName(), localChangeList.getComment(), localChange); - } - } - return intersection; - } - - @Nullable - private File getLocalPath(final String relativeToRepoPath) { - // from source if not inverted - final String pathToCheck = SVNPathUtil.append(myMergeContext.getWcInfo().getRepositoryRoot(), relativeToRepoPath); - final SvnBranchPointsCalculator.BranchCopyData wrapped = myCopyPoint.getWrapped(); - final String relativeInSource = - SVNPathUtil.getRelativePath(myCopyPoint.isInvertedSense() ? wrapped.getSource() : wrapped.getTarget(), pathToCheck); - if (StringUtil.isEmptyOrSpaces(relativeInSource)) return null; - final File local = new File(myMergeContext.getWcInfo().getPath(), relativeInSource); - return local; - } - - @Override - public void run(ContinuationContext context) { - final Intersection intersection; - final ChangeListManager listManager = ChangeListManager.getInstance(myMergeContext.getProject()); - final List localChangeLists = listManager.getChangeListsCopy(); - - if (myMergeAll) { - intersection = getMergeAllIntersection(localChangeLists); - } else { - intersection = checkIntersection(myLists, localChangeLists); - } - if (intersection == null || intersection.getChangesSubset().isEmpty()) return; - - final LocalChangesAction action = myInteraction.selectLocalChangesAction(myMergeAll); - switch (action) { - // shelve - case shelve: - context.next(new ShelveLocalChanges(myMergeContext, myInteraction, intersection)); - return; - // cancel - case cancel: - context.cancelEverything(); - return; - // continue - case continueMerge: - return; - // inspect - case inspect: - // here's cast is due to generic's bug - @SuppressWarnings("unchecked") final Collection changes = (Collection) intersection.getChangesSubset().values(); - final List paths = ChangesUtil.getPaths(changes); - Collections.sort(paths, FilePathByPathComparator.getInstance()); - myInteraction.showIntersectedLocalPaths(paths); - context.cancelEverything(); - return; - default: - } - } - - @Nullable - private Intersection checkIntersection(@Nullable final List lists, List localChangeLists) { - if (lists == null || lists.isEmpty()) { - return null; - } - final Set mergePaths = new HashSet(); - for (CommittedChangeList list : lists) { - final SvnChangeList svnList = (SvnChangeList)list; - final List paths = new ArrayList(svnList.getAddedPaths()); - paths.addAll(svnList.getChangedPaths()); - paths.addAll(svnList.getDeletedPaths()); - for (String path : paths) { - final File localPath = getLocalPath(path); - if (localPath != null) { - mergePaths.add(new FilePathImpl(localPath, false)); - } - } - } - - final Intersection intersection = new Intersection(); - for (LocalChangeList localChangeList : localChangeLists) { - final Collection localChanges = localChangeList.getChanges(); - - for (Change localChange : localChanges) { - final FilePath before = localChange.getBeforeRevision() == null ? null : localChange.getBeforeRevision().getFile(); - final FilePath after = localChange.getAfterRevision() == null ? null : localChange.getAfterRevision().getFile(); - - if ((before != null && mergePaths.contains(before)) || (after != null && mergePaths.contains(after))) { - intersection.add(localChangeList.getName(), localChangeList.getComment(), localChange); - } - } - } - return intersection; - } - } - - private static class ShelveLocalChanges extends BaseMergeTask { - private final Intersection myIntersection; - - private ShelveLocalChanges(@NotNull MergeContext mergeContext, - @NotNull QuickMergeInteraction interaction, - final Intersection intersection) { - super(mergeContext, interaction, "Shelving local changes before merge", Where.POOLED); - myIntersection = intersection; - } - - @Override - public void run(final ContinuationContext context) { - final MultiMap map = myIntersection.getChangesSubset(); - - final RefreshSessionImpl session = new RefreshSessionImpl(true, false, new Runnable() { - public void run() { - context.ping(); - } - }); - - for (String name : map.keySet()) { - try { - final Collection changes = map.get(name); - ApplicationManager.getApplication().invokeAndWait(new Runnable() { - @Override - public void run() { - FileDocumentManager.getInstance().saveAllDocuments(); - } - }, ModalityState.NON_MODAL); - ShelveChangesManager.getInstance(myMergeContext.getProject()).shelveChanges(changes, myIntersection.getComment(name) + - " (auto shelve before merge)", - true - ); - session.addAllFiles(ChangesUtil.getFilesFromChanges(changes)); - } - catch (IOException e) { - finishWithError(context, e.getMessage(), true); - } - catch (VcsException e) { - finishWithError(context, e.getMessage(), true); - } - } - // first suspend to guarantee stop->then start back sequence - context.suspend(); - session.launch(); - } - } - - private static class Intersection { - private final Map myLists; - private final MultiMap myChangesSubset; - - private Intersection() { - myLists = new HashMap(); - myChangesSubset = new MultiMap(); - } - - public void add(@NotNull final String listName, @Nullable final String comment, final Change change) { - myChangesSubset.putValue(listName, change); - final String commentToPut = comment == null ? listName : comment; - myLists.put(listName, commentToPut); - } - - public String getComment(final String listName) { - return myLists.get(listName); - } - - public MultiMap getChangesSubset() { - return myChangesSubset; - } - } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/BaseMergeTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/BaseMergeTask.java new file mode 100644 index 000000000000..f9c3f7821b19 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/BaseMergeTask.java @@ -0,0 +1,90 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.vcs.CalledInAny; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.TaskDescriptor; +import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.dialogs.MergeContext; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Konstantin Kolosovsky. + */ +public abstract class BaseMergeTask extends TaskDescriptor { + + private static final Logger LOG = Logger.getInstance(BaseMergeTask.class); + + @NotNull protected final MergeContext myMergeContext; + @NotNull protected final QuickMergeInteraction myInteraction; + + public BaseMergeTask(@NotNull MergeContext mergeContext, + @NotNull QuickMergeInteraction interaction, String name, + @NotNull Where where) { + super(name, where); + myMergeContext = mergeContext; + myInteraction = interaction; + } + + protected void insertMergeAll(final ContinuationContext context) { + final List queue = new ArrayList(); + insertMergeAll(queue); + context.next(queue); + } + + protected void insertMergeAll(final List queue) { + queue.add(new LocalChangesPromptTask(myMergeContext, myInteraction, true, null, null)); + final MergeAllWithBranchCopyPointTask mergeAllExecutor = new MergeAllWithBranchCopyPointTask(myMergeContext, myInteraction); + queue.add(myMergeContext.getVcs().getSvnBranchPointsCalculator() + .getFirstCopyPointTask(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl(), + myMergeContext.getWcInfo().getRootUrl(), mergeAllExecutor)); + queue.add(mergeAllExecutor); + } + + @CalledInAny + protected void finishWithError(final ContinuationContext context, final String message, final boolean isError) { + LOG.info((isError ? "Error: " : "Info: ") + message); + context.next(new TaskDescriptor(message, Where.AWT) { + @Override + public void run(ContinuationContext context) { + myInteraction.showErrors(message, isError); + context.cancelEverything(); + } + }); + } + + @CalledInAny + protected void finishWithError(final ContinuationContext context, final String message, final List exceptions) { + if (exceptions != null) { + for (VcsException exception : exceptions) { + LOG.info(message, exception); + } + } + context.cancelEverything(); + context.next(new TaskDescriptor(message, Where.AWT) { + @Override + public void run(ContinuationContext context) { + myInteraction.showErrors(message, exceptions); + } + }); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/CheckRepositorySupportsMergeInfoTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/CheckRepositorySupportsMergeInfoTask.java new file mode 100644 index 000000000000..5bb178b03192 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/CheckRepositorySupportsMergeInfoTask.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.TaskDescriptor; +import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnUtil; +import org.jetbrains.idea.svn.dialogs.MergeContext; + +import java.util.LinkedList; +import java.util.List; + +/** + * @author Konstantin Kolosovsky. + */ +public class CheckRepositorySupportsMergeInfoTask extends BaseMergeTask { + + public CheckRepositorySupportsMergeInfoTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { + super(mergeContext, interaction, "Checking repository capabilities", Where.POOLED); + } + + @Override + public void run(ContinuationContext context) { + final List tasks = new LinkedList(); + final boolean supportsMergeinfo = myMergeContext.getWcInfo().getFormat().supportsMergeInfo() && SvnUtil.checkRepositoryVersion15( + myMergeContext.getVcs(), myMergeContext.getSourceUrl()); + if (!supportsMergeinfo) { + insertMergeAll(tasks); + } + else { + tasks.add(new MergeAllOrSelectedChooserTask(myMergeContext, myInteraction)); + } + context.next(tasks); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Intersection.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Intersection.java new file mode 100644 index 000000000000..439fc7fecbf3 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Intersection.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.util.containers.MultiMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +/** +* @author Konstantin Kolosovsky. +*/ +public class Intersection { + private final Map myLists; + private final MultiMap myChangesSubset; + + public Intersection() { + myLists = new HashMap(); + myChangesSubset = new MultiMap(); + } + + public void add(@NotNull final String listName, @Nullable final String comment, final Change change) { + myChangesSubset.putValue(listName, change); + final String commentToPut = comment == null ? listName : comment; + myLists.put(listName, commentToPut); + } + + public String getComment(final String listName) { + return myLists.get(listName); + } + + public MultiMap getChangesSubset() { + return myChangesSubset; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/LocalChangesPromptTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/LocalChangesPromptTask.java new file mode 100644 index 000000000000..2652c79b5c11 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/LocalChangesPromptTask.java @@ -0,0 +1,155 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.FilePathImpl; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.ChangesUtil; +import com.intellij.openapi.vcs.changes.LocalChangeList; +import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; +import com.intellij.util.FilePathByPathComparator; +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.dialogs.LocalChangesAction; +import org.jetbrains.idea.svn.dialogs.MergeContext; +import org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator; +import org.jetbrains.idea.svn.history.SvnChangeList; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; + +import java.io.File; +import java.util.*; + +/** + * @author Konstantin Kolosovsky. + */ +public class LocalChangesPromptTask extends BaseMergeTask { + private final boolean myMergeAll; + @Nullable private final List myLists; + private final SvnBranchPointsCalculator.WrapperInvertor myCopyPoint; + + public LocalChangesPromptTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction, final boolean mergeAll, + @Nullable final List lists, + @Nullable SvnBranchPointsCalculator.WrapperInvertor copyPoint) { + super(mergeContext, interaction, "local changes intersection check", Where.AWT); + myMergeAll = mergeAll; + myLists = lists; + myCopyPoint = copyPoint; + } + + private static Intersection getMergeAllIntersection(List localChangeLists) { + final Intersection intersection = new Intersection(); + + for (LocalChangeList localChangeList : localChangeLists) { + final Collection localChanges = localChangeList.getChanges(); + for (Change localChange : localChanges) { + intersection.add(localChangeList.getName(), localChangeList.getComment(), localChange); + } + } + return intersection; + } + + @Nullable + private File getLocalPath(final String relativeToRepoPath) { + // from source if not inverted + final String pathToCheck = SVNPathUtil.append(myMergeContext.getWcInfo().getRepositoryRoot(), relativeToRepoPath); + final SvnBranchPointsCalculator.BranchCopyData wrapped = myCopyPoint.getWrapped(); + final String relativeInSource = + SVNPathUtil.getRelativePath(myCopyPoint.isInvertedSense() ? wrapped.getSource() : wrapped.getTarget(), pathToCheck); + if (StringUtil.isEmptyOrSpaces(relativeInSource)) return null; + final File local = new File(myMergeContext.getWcInfo().getPath(), relativeInSource); + return local; + } + + @Override + public void run(ContinuationContext context) { + final Intersection intersection; + final ChangeListManager listManager = ChangeListManager.getInstance(myMergeContext.getProject()); + final List localChangeLists = listManager.getChangeListsCopy(); + + if (myMergeAll) { + intersection = getMergeAllIntersection(localChangeLists); + } + else { + intersection = checkIntersection(myLists, localChangeLists); + } + if (intersection == null || intersection.getChangesSubset().isEmpty()) return; + + final LocalChangesAction action = myInteraction.selectLocalChangesAction(myMergeAll); + switch (action) { + // shelve + case shelve: + context.next(new ShelveLocalChangesTask(myMergeContext, myInteraction, intersection)); + return; + // cancel + case cancel: + context.cancelEverything(); + return; + // continue + case continueMerge: + return; + // inspect + case inspect: + // here's cast is due to generic's bug + @SuppressWarnings("unchecked") final Collection changes = (Collection)intersection.getChangesSubset().values(); + final List paths = ChangesUtil.getPaths(changes); + Collections.sort(paths, FilePathByPathComparator.getInstance()); + myInteraction.showIntersectedLocalPaths(paths); + context.cancelEverything(); + return; + default: + } + } + + @Nullable + private Intersection checkIntersection(@Nullable final List lists, List localChangeLists) { + if (lists == null || lists.isEmpty()) { + return null; + } + final Set mergePaths = new HashSet(); + for (CommittedChangeList list : lists) { + final SvnChangeList svnList = (SvnChangeList)list; + final List paths = new ArrayList(svnList.getAddedPaths()); + paths.addAll(svnList.getChangedPaths()); + paths.addAll(svnList.getDeletedPaths()); + for (String path : paths) { + final File localPath = getLocalPath(path); + if (localPath != null) { + mergePaths.add(new FilePathImpl(localPath, false)); + } + } + } + + final Intersection intersection = new Intersection(); + for (LocalChangeList localChangeList : localChangeLists) { + final Collection localChanges = localChangeList.getChanges(); + + for (Change localChange : localChanges) { + final FilePath before = localChange.getBeforeRevision() == null ? null : localChange.getBeforeRevision().getFile(); + final FilePath after = localChange.getAfterRevision() == null ? null : localChange.getAfterRevision().getFile(); + + if ((before != null && mergePaths.contains(before)) || (after != null && mergePaths.contains(after))) { + intersection.add(localChangeList.getName(), localChangeList.getComment(), localChange); + } + } + } + return intersection; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java new file mode 100644 index 000000000000..7827fb87f043 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java @@ -0,0 +1,65 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.openapi.vcs.VcsException; +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.dialogs.LoadRecentBranchRevisions; +import org.jetbrains.idea.svn.dialogs.MergeContext; +import org.jetbrains.idea.svn.dialogs.QuickMergeContentsVariants; + +/** + * @author Konstantin Kolosovsky. + */ +public class MergeAllOrSelectedChooserTask extends BaseMergeTask { + public MergeAllOrSelectedChooserTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { + super(mergeContext, interaction, "merge source selector", Where.AWT); + } + + @Override + public void run(final ContinuationContext context) { + final QuickMergeContentsVariants variant = myInteraction.selectMergeVariant(); + if (QuickMergeContentsVariants.cancel == variant) return; + if (QuickMergeContentsVariants.all == variant) { + insertMergeAll(context); + return; + } + if (QuickMergeContentsVariants.showLatest == variant) { + final LoadRecentBranchRevisions loader = + new LoadRecentBranchRevisions(myMergeContext.getBranchName(), -1, myMergeContext.getWcInfo(), myMergeContext + .getVcs(), myMergeContext.getSourceUrl()); + final ShowRecentInDialogTask dialog = new ShowRecentInDialogTask(myMergeContext, myInteraction, loader); + context.next(loader, dialog); + return; + } + + final MergeCalculatorTask calculator; + try { + calculator = new MergeCalculatorTask(myMergeContext, myInteraction, myMergeContext.getWcInfo(), myMergeContext.getSourceUrl(), + myMergeContext.getBranchName() + ); + } + catch (VcsException e) { + finishWithError(context, e.getMessage(), true); + return; + } + context.next(myMergeContext.getVcs().getSvnBranchPointsCalculator() + .getFirstCopyPointTask(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getWcInfo().getRootUrl(), + myMergeContext.getSourceUrl(), calculator), calculator); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllWithBranchCopyPointTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllWithBranchCopyPointTask.java new file mode 100644 index 000000000000..8c5921675bd5 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllWithBranchCopyPointTask.java @@ -0,0 +1,94 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.TransparentlyFailedValueI; +import com.intellij.util.Consumer; +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.dialogs.BranchMerger; +import org.jetbrains.idea.svn.dialogs.MergeContext; +import org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator; +import org.jetbrains.idea.svn.update.UpdateEventHandler; +import org.tmatesoft.svn.core.SVNURL; + +import java.io.File; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @author Konstantin Kolosovsky. + */ +public class MergeAllWithBranchCopyPointTask extends BaseMergeTask + implements Consumer> { + + private final AtomicReference> myData; + + public MergeAllWithBranchCopyPointTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { + super(mergeContext, interaction, "merge all", Where.AWT); + myData = new AtomicReference>(); + } + + @Override + public void consume(TransparentlyFailedValueI value) { + myData.set(value); + } + + @Override + public void run(ContinuationContext context) { + SvnBranchPointsCalculator.WrapperInvertor invertor; + try { + final TransparentlyFailedValueI + transparentlyFailedValueI = myData.get(); + if (transparentlyFailedValueI == null) { + finishWithError(context, "Merge start wasn't found", true); + return; + } + invertor = transparentlyFailedValueI.get(); + } + catch (VcsException e) { + finishWithError(context, "Merge start wasn't found", Collections.singletonList(e)); + return; + } + if (invertor == null) { + finishWithError(context, "Merge start wasn't found", true); + return; + } + final boolean reintegrate = invertor.isInvertedSense(); + if (reintegrate && (!myInteraction.shouldReintegrate(myMergeContext.getSourceUrl(), invertor.inverted().getTarget()))) { + context.cancelEverything(); + return; + } + final MergerFactory mergerFactory = createBranchMergerFactory(reintegrate, invertor); + + final String title = "Merging all from " + myMergeContext.getBranchName() + (reintegrate ? " (reintegrate)" : ""); + context.next(new MergeTask(myMergeContext, myInteraction, mergerFactory, title)); + } + + private MergerFactory createBranchMergerFactory(final boolean reintegrate, + final SvnBranchPointsCalculator.WrapperInvertor invertor) { + return new MergerFactory() { + public IMerger createMerger(SvnVcs vcs, File target, UpdateEventHandler handler, SVNURL currentBranchUrl, String branchName) { + return new BranchMerger(vcs, currentBranchUrl, myMergeContext.getWcInfo().getUrl(), myMergeContext.getWcInfo().getPath(), handler, + reintegrate, myMergeContext.getBranchName(), + reintegrate ? invertor.getWrapped().getTargetRevision() : invertor.getWrapped().getSourceRevision()); + } + }; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java new file mode 100644 index 000000000000..bd19f70bf420 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java @@ -0,0 +1,275 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.TransparentlyFailedValueI; +import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; +import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; +import com.intellij.util.Consumer; +import com.intellij.util.PairConsumer; +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.TaskDescriptor; +import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.actions.ChangeListsMergerFactory; +import org.jetbrains.idea.svn.dialogs.MergeContext; +import org.jetbrains.idea.svn.dialogs.QuickMergeContentsVariants; +import org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator; +import org.jetbrains.idea.svn.dialogs.WCInfo; +import org.jetbrains.idea.svn.history.SvnChangeList; +import org.jetbrains.idea.svn.history.SvnCommittedChangesProvider; +import org.jetbrains.idea.svn.history.SvnRepositoryLocation; +import org.jetbrains.idea.svn.history.TreeStructureNode; +import org.jetbrains.idea.svn.mergeinfo.MergeChecker; +import org.jetbrains.idea.svn.mergeinfo.OneShotMergeInfoHelper; +import org.jetbrains.idea.svn.mergeinfo.SvnMergeInfoCache; +import org.jetbrains.idea.svn.update.UpdateEventHandler; +import org.tmatesoft.svn.core.SVNLogEntry; +import org.tmatesoft.svn.core.SVNLogEntryPath; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; + +import java.io.File; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @author Konstantin Kolosovsky. + */ +public class MergeCalculatorTask extends BaseMergeTask implements + Consumer> { + private final static String ourOneShotStrategy = "svn.quickmerge.oneShotStrategy"; + private final WCInfo myWcInfo; + private final String mySourceUrl; + private final String myBranchName; + private final + AtomicReference> + myCopyData; + private boolean myIsReintegrate; + + private final List myNotMerged; + private String myMergeTitle; + private final MergeChecker myMergeChecker; + + @Override + public void consume(TransparentlyFailedValueI value) { + myCopyData.set(value); + } + + public MergeCalculatorTask(@NotNull MergeContext mergeContext, + @NotNull QuickMergeInteraction interaction, WCInfo wcInfo, + String sourceUrl, + String branchName) throws VcsException { + super(mergeContext, interaction, "Calculating not merged revisions", Where.POOLED); + myWcInfo = wcInfo; + mySourceUrl = sourceUrl; + myBranchName = branchName; + myNotMerged = new LinkedList(); + myMergeTitle = "Merge from " + branchName; + // if (Boolean.TRUE.equals(Boolean.getBoolean(ourOneShotStrategy))) { + myMergeChecker = new OneShotMergeInfoHelper(myMergeContext.getProject(), myWcInfo, mySourceUrl); + ((OneShotMergeInfoHelper)myMergeChecker).prepare(); +/* } else { + myMergeChecker = new BranchInfo.MyMergeCheckerWrapper(myWcInfo.getPath(), new BranchInfo(myVcs, myWcInfo.getRepositoryRoot(), + myWcInfo.getRootUrl(), mySourceUrl, + mySourceUrl, myVcs.createWCClient())); + }*/ + myCopyData = new AtomicReference>(); + } + + //"Calculating not merged revisions" + @Override + public void run(ContinuationContext context) { + SvnBranchPointsCalculator.WrapperInvertor copyDataValue = null; + try { + copyDataValue = myCopyData.get().get(); + } + catch (VcsException e) { + finishWithError(context, "Merge start wasn't found", Collections.singletonList(e)); + return; + } + if (copyDataValue == null) { + finishWithError(context, "Merge start wasn't found", true); + return; + } + + final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); + myIsReintegrate = copyDataValue.isInvertedSense(); + if (!myWcInfo.getFormat().supportsMergeInfo()) return; + final SvnBranchPointsCalculator.BranchCopyData data = copyDataValue.getTrue(); + final long sourceLatest = data.getTargetRevision(); + + final SvnCommittedChangesProvider committedChangesProvider = + (SvnCommittedChangesProvider)myMergeContext.getVcs().getCommittedChangesProvider(); + final ChangeBrowserSettings settings = new ChangeBrowserSettings(); + settings.CHANGE_AFTER = Long.toString(sourceLatest); + settings.USE_CHANGE_AFTER_FILTER = true; + + String local = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), myWcInfo.getRootUrl()); + final String relativeLocal = (local.startsWith("/") ? local : "/" + local); + String relativeBranch = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), mySourceUrl); + relativeBranch = (relativeBranch.startsWith("/") ? relativeBranch : "/" + relativeBranch); + + final LinkedList>> list = + new LinkedList>>(); + try { + committedChangesProvider.getCommittedChangesWithMergedRevisons(settings, new SvnRepositoryLocation(mySourceUrl), 0, + new PairConsumer>() { + public void consume(SvnChangeList svnList, + TreeStructureNode tree) { + indicator.checkCanceled(); + if (sourceLatest >= svnList.getNumber()) return; + list.add( + new Pair>(svnList, + tree) + ); + } + } + ); + } + catch (VcsException e) { + finishWithError(context, "Checking revisions for merge fault", Collections.singletonList(e)); + } + + indicator.setText("Checking merge information..."); + // to do not go into file system while asking something on the net + for (Pair> pair : list) { + final SvnChangeList svnList = pair.getFirst(); + final SvnMergeInfoCache.MergeCheckResult checkResult = myMergeChecker.checkList(svnList); + indicator.setText2("Processing revision " + svnList.getNumber()); + + if (SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(checkResult)) { + // additionally check for being 'local' + boolean localChange = checkListForPaths(relativeLocal, relativeBranch, pair); + + if (!localChange) { + myNotMerged.add(svnList); + } + } + } + + if (myNotMerged.isEmpty()) { + finishWithError(context, "Everything is up-to-date", false); + return; + } + context.next(new ShowRevisionSelector(copyDataValue)); + } + + private class ShowRevisionSelector extends TaskDescriptor { + private final SvnBranchPointsCalculator.WrapperInvertor myCopyPoint; + + private ShowRevisionSelector(SvnBranchPointsCalculator.WrapperInvertor copyPoint) { + super("show revisions to merge", Where.AWT); + myCopyPoint = copyPoint; + } + + @Override + public void run(ContinuationContext context) { + final QuickMergeInteraction.SelectMergeItemsResult result = myInteraction.selectMergeItems(myNotMerged, myMergeTitle, myMergeChecker); + if (QuickMergeContentsVariants.cancel == result.getResultCode()) { + context.cancelEverything(); + return; + } + if (QuickMergeContentsVariants.all == result.getResultCode()) { + insertMergeAll(context); + } + else { + final List lists = result.getSelectedLists(); + if (lists.isEmpty()) return; + final MergerFactory factory = new ChangeListsMergerFactory(lists) { + @Override + public IMerger createMerger(SvnVcs vcs, File target, UpdateEventHandler handler, SVNURL currentBranchUrl, String branchName) { + return new GroupMerger(vcs, lists, target, handler, currentBranchUrl, branchName, false, false, false); + } + }; + context.next(new LocalChangesPromptTask(myMergeContext, myInteraction, false, lists, myCopyPoint), new MergeTask(myMergeContext, + myInteraction, + factory, + myMergeTitle + )); + } + } + } + + // true if errors found + static boolean checkListForPaths(String relativeLocal, + String relativeBranch, Pair> pair) { + // TODO: Such filtering logic is not clear enough so far (and probably not correct for all cases - for instance when we perform merge + // TODO: from branch1 to branch2 and have revision which contain merge changes from branch3 to branch1. + // TODO: In this case paths of child log entries will not contain neither urls from branch1 nor from branch2 - and checkEntry() method + // TODO: will return true => so such revision will not be used (and displayed) further. + + // TODO: Why do we check entries recursively - we have a revision - set of changes in the "merge from" branch? Why do we need to check + // TODO: where they came from - we want avoid some circular merges or what? Does subversion itself perform such checks or not? + final List> children = pair.getSecond().getChildren(); + boolean localChange = false; + for (TreeStructureNode child : children) { + if (checkForSubtree(child, relativeLocal, relativeBranch)) { + localChange = true; + break; + } + } + if (!localChange) { + // check self + return checkForEntry(pair.getSecond().getMe(), relativeLocal, relativeBranch); + } + return localChange; + } + + // true if errors found + private static boolean checkForSubtree(final TreeStructureNode tree, + String relativeBranch, final String localURL) { + final LinkedList> queue = new LinkedList>(); + queue.addLast(tree); + + while (!queue.isEmpty()) { + final TreeStructureNode element = queue.removeFirst(); + ProgressManager.checkCanceled(); + + if (checkForEntry(element.getMe(), localURL, relativeBranch)) return true; + queue.addAll(element.getChildren()); + } + return false; + } + + // true if errors found + // checks if either some changed path is in current branch => treat as local change + // or if no changed paths in current branch, checks if at least one path in "merge from" branch + // NOTE: this fails for "merge-source" log entries from other branches - when all changed paths are from some + // third branch - this logic treats such log entry as local. + private static boolean checkForEntry(final SVNLogEntry entry, final String localURL, String relativeBranch) { + boolean atLeastOneUnderBranch = false; + final Map map = entry.getChangedPaths(); + for (Object o : map.values()) { + final SVNLogEntryPath path = (SVNLogEntryPath)o; + if (SVNPathUtil.isAncestor(localURL, path.getPath())) { + return true; + } + if (!atLeastOneUnderBranch && SVNPathUtil.isAncestor(relativeBranch, path.getPath())) { + atLeastOneUnderBranch = true; + } + } + return !atLeastOneUnderBranch; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeInitChecksTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeInitChecksTask.java new file mode 100644 index 000000000000..a5b5c8ee870b --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeInitChecksTask.java @@ -0,0 +1,90 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.NestedCopyType; +import org.jetbrains.idea.svn.SvnUtil; +import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.jetbrains.idea.svn.dialogs.MergeContext; +import org.jetbrains.idea.svn.dialogs.WCInfo; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.internal.util.SVNURLUtil; + +import java.io.File; +import java.util.List; + +/** + * @author Konstantin Kolosovsky. + */ +public class MergeInitChecksTask extends BaseMergeTask { + + public MergeInitChecksTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { + super(mergeContext, interaction, "initial checks", Where.AWT); + } + + @Override + public void run(ContinuationContext continuationContext) { + SVNURL url = parseUrl(continuationContext); + if (url == null) { + return; + } + + if (SVNURLUtil.isAncestor(url, myMergeContext.getWcInfo().getUrl()) || + SVNURLUtil.isAncestor(myMergeContext.getWcInfo().getUrl(), url)) { + finishWithError(continuationContext, "Cannot merge from self", true); + return; + } + + if (!checkForSwitchedRoots()) { + continuationContext.cancelEverything(); + } + } + + private boolean checkForSwitchedRoots() { + final List infoList = myMergeContext.getVcs().getAllWcInfos(); + boolean switchedFound = false; + for (WCInfo wcInfo : infoList) { + if (FileUtil.isAncestor(new File(myMergeContext.getWcInfo().getPath()), new File(wcInfo.getPath()), true) + && NestedCopyType.switched.equals(wcInfo.getType())) { + switchedFound = true; + break; + } + } + if (switchedFound) { + return myInteraction.shouldContinueSwitchedRootFound(); + } + return true; + } + + @Nullable + private SVNURL parseUrl(ContinuationContext continuationContext) { + SVNURL url = null; + + try { + url = SvnUtil.createUrl(myMergeContext.getSourceUrl()); + } + catch (SvnBindException e) { + finishWithError(continuationContext, e.getMessage(), true); + } + + return url; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeTask.java new file mode 100644 index 000000000000..6367ce4cdc0e --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeTask.java @@ -0,0 +1,99 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.InvokeAfterUpdateMode; +import com.intellij.openapi.vcs.changes.LocalChangeList; +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.ContinuationPause; +import com.intellij.util.continuation.TaskDescriptor; +import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.dialogs.MergeContext; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; + +/** + * @author Konstantin Kolosovsky. + */ +public class MergeTask extends BaseMergeTask { + private final MergerFactory myFactory; + + // awt since only a wrapper + public MergeTask(@NotNull MergeContext mergeContext, + @NotNull QuickMergeInteraction interaction, final MergerFactory factory, + final String mergeTitle) { + super(mergeContext, interaction, mergeTitle, Where.AWT); + myFactory = factory; + } + + @Override + public void run(ContinuationContext context) { + final SVNURL sourceUrlUrl; + try { + sourceUrlUrl = SVNURL.parseURIEncoded(myMergeContext.getSourceUrl()); + } + catch (SVNException e) { + finishWithError(context, "Cannot merge: " + e.getMessage(), true); + return; + } + + final SvnIntegrateChangesTask task = new SvnIntegrateChangesTask(myMergeContext.getVcs(), + new WorkingCopyInfo(myMergeContext.getWcInfo().getPath(), true), + myFactory, sourceUrlUrl, getName(), false, + myMergeContext.getBranchName()); + final TaskDescriptor taskDescriptor = TaskDescriptor.createForBackgroundableTask(task); + // merge task will be the next after... + context.next(taskDescriptor); + // ... after we create changelist + createChangelist(context); + } + + private void createChangelist(final ContinuationPause context) { + final ChangeListManager listManager = ChangeListManager.getInstance(myMergeContext.getProject()); + String name = myMergeContext.getTitle(); + int i = 1; + boolean updateDefaultList = false; + while (true) { + final LocalChangeList changeList = listManager.findChangeList(name); + if (changeList == null) { + final LocalChangeList newList = listManager.addChangeList(name, null); + listManager.setDefaultChangeList(newList); + updateDefaultList = true; + break; + } + if (changeList.getChanges().isEmpty()) { + if (!changeList.isDefault()) { + listManager.setDefaultChangeList(changeList); + updateDefaultList = true; + } + break; + } + name = myMergeContext.getTitle() + " (" + i + ")"; + ++i; + } + if (updateDefaultList) { + context.suspend(); + listManager.invokeAfterUpdate(new Runnable() { + public void run() { + context.ping(); + } + }, InvokeAfterUpdateMode.BACKGROUND_NOT_CANCELLABLE_NOT_AWT, "", ModalityState.NON_MODAL); + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShelveLocalChangesTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShelveLocalChangesTask.java new file mode 100644 index 000000000000..0c1f2313ca37 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShelveLocalChangesTask.java @@ -0,0 +1,84 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ChangesUtil; +import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager; +import com.intellij.openapi.vfs.newvfs.RefreshSessionImpl; +import com.intellij.util.containers.MultiMap; +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.dialogs.MergeContext; + +import java.io.IOException; +import java.util.Collection; + +/** + * @author Konstantin Kolosovsky. + */ +public class ShelveLocalChangesTask extends BaseMergeTask { + private final Intersection myIntersection; + + public ShelveLocalChangesTask(@NotNull MergeContext mergeContext, + @NotNull QuickMergeInteraction interaction, + final Intersection intersection) { + super(mergeContext, interaction, "Shelving local changes before merge", Where.POOLED); + myIntersection = intersection; + } + + @Override + public void run(final ContinuationContext context) { + final MultiMap map = myIntersection.getChangesSubset(); + + final RefreshSessionImpl session = new RefreshSessionImpl(true, false, new Runnable() { + public void run() { + context.ping(); + } + }); + + for (String name : map.keySet()) { + try { + final Collection changes = map.get(name); + ApplicationManager.getApplication().invokeAndWait(new Runnable() { + @Override + public void run() { + FileDocumentManager.getInstance().saveAllDocuments(); + } + }, ModalityState.NON_MODAL); + ShelveChangesManager.getInstance(myMergeContext.getProject()).shelveChanges(changes, myIntersection.getComment(name) + + " (auto shelve before merge)", + true + ); + session.addAllFiles(ChangesUtil.getFilesFromChanges(changes)); + } + catch (IOException e) { + finishWithError(context, e.getMessage(), true); + } + catch (VcsException e) { + finishWithError(context, e.getMessage(), true); + } + } + // first suspend to guarantee stop->then start back sequence + context.suspend(); + session.launch(); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShowRecentInDialogTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShowRecentInDialogTask.java new file mode 100644 index 000000000000..5a094b700bbe --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShowRecentInDialogTask.java @@ -0,0 +1,114 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.ui.popup.util.PopupUtil; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList; +import com.intellij.util.Consumer; +import com.intellij.util.PairConsumer; +import com.intellij.util.continuation.Continuation; +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.TaskDescriptor; +import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.actions.ChangeListsMergerFactory; +import org.jetbrains.idea.svn.dialogs.LoadRecentBranchRevisions; +import org.jetbrains.idea.svn.dialogs.MergeContext; +import org.jetbrains.idea.svn.dialogs.MergeDialogI; +import org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator; +import org.jetbrains.idea.svn.update.UpdateEventHandler; +import org.tmatesoft.svn.core.SVNURL; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +/** + * @author Konstantin Kolosovsky. + */ +public class ShowRecentInDialogTask extends BaseMergeTask { + private final LoadRecentBranchRevisions myLoader; + + public ShowRecentInDialogTask(@NotNull MergeContext mergeContext, + @NotNull QuickMergeInteraction interaction, + LoadRecentBranchRevisions loader) { + super(mergeContext, interaction, "", Where.AWT); + myLoader = loader; + } + + @Override + public void run(ContinuationContext context) { + final PairConsumer loader = new PairConsumer() { + @Override + public void consume(Long bunchSize, final MergeDialogI dialog) { + final LoadRecentBranchRevisions loader = + new LoadRecentBranchRevisions( + myMergeContext.getBranchName(), dialog.getLastNumber(), myMergeContext.getWcInfo(), myMergeContext.getVcs(), + myMergeContext.getSourceUrl(), bunchSize.intValue()); + final TaskDescriptor updater = new TaskDescriptor("", Where.AWT) { + @Override + public void run(ContinuationContext context) { + dialog.addMoreLists(loader.getCommittedChangeLists()); + if (loader.isLastLoaded()) { + dialog.setEverythingLoaded(true); + } + } + + @Override + public void canceled() { + dialog.addMoreLists(Collections.emptyList()); + dialog.setEverythingLoaded(true); + } + }; + final Continuation fragmented = Continuation.createFragmented(myMergeContext.getProject(), true); + fragmented.addExceptionHandler(VcsException.class, new Consumer() { + @Override + public void consume(VcsException e) { + PopupUtil.showBalloonForActiveComponent(e.getMessage() == null ? e.getClass().getName() : e.getMessage(), MessageType.ERROR); + } + }); + fragmented.run(loader, updater); + } + }; + final List lists = myInteraction.showRecentListsForSelection(myLoader.getCommittedChangeLists(), + myMergeContext.getTitle(), myLoader.getHelper(), + loader, myLoader.isLastLoaded()); + + if (lists != null && !lists.isEmpty()) { + final MergerFactory factory = new ChangeListsMergerFactory(lists) { + @Override + public IMerger createMerger(SvnVcs vcs, File target, UpdateEventHandler handler, SVNURL currentBranchUrl, String branchName) { + return new GroupMerger(vcs, lists, target, handler, currentBranchUrl, branchName, false, false, false); + } + }; + // fictive branch point, just for + final SvnBranchPointsCalculator.BranchCopyData copyData = + new SvnBranchPointsCalculator.BranchCopyData(myMergeContext.getWcInfo().getUrl().toString(), -1, myMergeContext.getSourceUrl(), + -1); + context.next(new LocalChangesPromptTask(myMergeContext, myInteraction, + false, lists, new SvnBranchPointsCalculator.WrapperInvertor(false, copyData) + ), + new MergeTask(myMergeContext, myInteraction, factory, myMergeContext.getTitle()) + ); + } + else { + context.cancelEverything(); + } + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java new file mode 100644 index 000000000000..39d51de62943 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SourceUrlCorrectionTask.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.integrate; + +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnBranchConfigurationManager; +import org.jetbrains.idea.svn.dialogs.MergeContext; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; + +/** +* @author Konstantin Kolosovsky. +*/ +public class SourceUrlCorrectionTask extends BaseMergeTask { + + public SourceUrlCorrectionTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) { + super(mergeContext, interaction, "Checking branch", Where.POOLED); + } + + @Override + public void run(ContinuationContext continuationContext) { + final SVNURL branch = + SvnBranchConfigurationManager.getInstance(myMergeContext.getProject()).getSvnBranchConfigManager().getWorkingBranchWithReload( + myMergeContext.getWcInfo().getUrl(), myMergeContext.getRoot()); + if (branch != null && (!myMergeContext.getWcInfo().getUrl().equals(branch))) { + final String branchString = branch.toString(); + if (SVNPathUtil.isAncestor(branchString, myMergeContext.getWcInfo().getRootUrl())) { + final String subPath = SVNPathUtil.getRelativePath(branchString, myMergeContext.getWcInfo().getRootUrl()); + myMergeContext.setSourceUrl(SVNPathUtil.append(myMergeContext.getSourceUrl(), subPath)); + } + } + } +} From 562e89d95682e7dc37db0f4f4f0bc85b2855e229 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 21 Apr 2014 16:37:05 +0400 Subject: [PATCH 17/65] svn: Refactored MergeCalculatorTask - removed unnecessary fields and utilize data from MergeContext instead --- .../MergeAllOrSelectedChooserTask.java | 4 +--- .../svn/integrate/MergeCalculatorTask.java | 24 ++++++------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java index 7827fb87f043..b4f19ae1e912 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java @@ -50,9 +50,7 @@ public class MergeAllOrSelectedChooserTask extends BaseMergeTask { final MergeCalculatorTask calculator; try { - calculator = new MergeCalculatorTask(myMergeContext, myInteraction, myMergeContext.getWcInfo(), myMergeContext.getSourceUrl(), - myMergeContext.getBranchName() - ); + calculator = new MergeCalculatorTask(myMergeContext, myInteraction); } catch (VcsException e) { finishWithError(context, e.getMessage(), true); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java index bd19f70bf420..a534e34b1dff 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java @@ -33,7 +33,6 @@ import org.jetbrains.idea.svn.actions.ChangeListsMergerFactory; import org.jetbrains.idea.svn.dialogs.MergeContext; import org.jetbrains.idea.svn.dialogs.QuickMergeContentsVariants; import org.jetbrains.idea.svn.dialogs.SvnBranchPointsCalculator; -import org.jetbrains.idea.svn.dialogs.WCInfo; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.history.SvnCommittedChangesProvider; import org.jetbrains.idea.svn.history.SvnRepositoryLocation; @@ -60,9 +59,6 @@ import java.util.concurrent.atomic.AtomicReference; public class MergeCalculatorTask extends BaseMergeTask implements Consumer> { private final static String ourOneShotStrategy = "svn.quickmerge.oneShotStrategy"; - private final WCInfo myWcInfo; - private final String mySourceUrl; - private final String myBranchName; private final AtomicReference> myCopyData; @@ -77,18 +73,12 @@ public class MergeCalculatorTask extends BaseMergeTask implements myCopyData.set(value); } - public MergeCalculatorTask(@NotNull MergeContext mergeContext, - @NotNull QuickMergeInteraction interaction, WCInfo wcInfo, - String sourceUrl, - String branchName) throws VcsException { + public MergeCalculatorTask(@NotNull MergeContext mergeContext, @NotNull QuickMergeInteraction interaction) throws VcsException { super(mergeContext, interaction, "Calculating not merged revisions", Where.POOLED); - myWcInfo = wcInfo; - mySourceUrl = sourceUrl; - myBranchName = branchName; myNotMerged = new LinkedList(); - myMergeTitle = "Merge from " + branchName; + myMergeTitle = "Merge from " + myMergeContext.getBranchName(); // if (Boolean.TRUE.equals(Boolean.getBoolean(ourOneShotStrategy))) { - myMergeChecker = new OneShotMergeInfoHelper(myMergeContext.getProject(), myWcInfo, mySourceUrl); + myMergeChecker = new OneShotMergeInfoHelper(myMergeContext.getProject(), myMergeContext.getWcInfo(), myMergeContext.getSourceUrl()); ((OneShotMergeInfoHelper)myMergeChecker).prepare(); /* } else { myMergeChecker = new BranchInfo.MyMergeCheckerWrapper(myWcInfo.getPath(), new BranchInfo(myVcs, myWcInfo.getRepositoryRoot(), @@ -116,7 +106,7 @@ public class MergeCalculatorTask extends BaseMergeTask implements final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); myIsReintegrate = copyDataValue.isInvertedSense(); - if (!myWcInfo.getFormat().supportsMergeInfo()) return; + if (!myMergeContext.getWcInfo().getFormat().supportsMergeInfo()) return; final SvnBranchPointsCalculator.BranchCopyData data = copyDataValue.getTrue(); final long sourceLatest = data.getTargetRevision(); @@ -126,15 +116,15 @@ public class MergeCalculatorTask extends BaseMergeTask implements settings.CHANGE_AFTER = Long.toString(sourceLatest); settings.USE_CHANGE_AFTER_FILTER = true; - String local = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), myWcInfo.getRootUrl()); + String local = SVNPathUtil.getRelativePath(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getWcInfo().getRootUrl()); final String relativeLocal = (local.startsWith("/") ? local : "/" + local); - String relativeBranch = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), mySourceUrl); + String relativeBranch = SVNPathUtil.getRelativePath(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl()); relativeBranch = (relativeBranch.startsWith("/") ? relativeBranch : "/" + relativeBranch); final LinkedList>> list = new LinkedList>>(); try { - committedChangesProvider.getCommittedChangesWithMergedRevisons(settings, new SvnRepositoryLocation(mySourceUrl), 0, + committedChangesProvider.getCommittedChangesWithMergedRevisons(settings, new SvnRepositoryLocation(myMergeContext.getSourceUrl()), 0, new PairConsumer>() { public void consume(SvnChangeList svnList, TreeStructureNode tree) { From 9fe9ac976ab37359c3967167bbc64b772cd71dc1 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 21 Apr 2014 17:12:49 +0400 Subject: [PATCH 18/65] svn: Refactored LoadRecentBranchRevisions - removed unnecessary fields and utilize MergeContext instead --- .../dialogs/LoadRecentBranchRevisions.java | 33 +++++++++---------- .../MergeAllOrSelectedChooserTask.java | 4 +-- .../svn/integrate/ShowRecentInDialogTask.java | 4 +-- 3 files changed, 17 insertions(+), 24 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java index 3d77b5da426b..a00cddf23ed2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java @@ -25,14 +25,13 @@ import com.intellij.util.PairConsumer; import com.intellij.util.continuation.ContinuationContext; import com.intellij.util.continuation.TaskDescriptor; import com.intellij.util.continuation.Where; +import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnBundle; -import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.history.SvnCommittedChangesProvider; import org.jetbrains.idea.svn.history.SvnRepositoryLocation; import org.jetbrains.idea.svn.history.TreeStructureNode; import org.jetbrains.idea.svn.mergeinfo.OneShotMergeInfoHelper; -import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNLogEntry; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; @@ -53,21 +52,17 @@ public class LoadRecentBranchRevisions extends TaskDescriptor { private boolean myLastLoaded; private OneShotMergeInfoHelper myHelper; private List myCommittedChangeLists; - private final WCInfo myWcInfo; - private final SvnVcs myVcs; - private final String mySourceUrl; private final Integer myTestBunchSize; + @NotNull private final MergeContext myMergeContext; - public LoadRecentBranchRevisions(String branchName, long first, WCInfo info, SvnVcs vcs, String url) { - this(branchName, first, info, vcs, url, -1); + public LoadRecentBranchRevisions(@NotNull MergeContext mergeContext, long first) { + this(mergeContext, first, -1); } - public LoadRecentBranchRevisions(String branchName, long first, WCInfo info, SvnVcs vcs, String url, final int bunchSize) { - super("Loading recent " + branchName + " revisions", Where.POOLED); + public LoadRecentBranchRevisions(@NotNull MergeContext mergeContext, long first, int bunchSize) { + super("Loading recent " + mergeContext.getBranchName() + " revisions", Where.POOLED); + myMergeContext = mergeContext; myFirst = first; - myWcInfo = info; - myVcs = vcs; - mySourceUrl = url; // for test purposes!!! myTestBunchSize = Integer.getInteger(PROP_BUNCH_SIZE); if (myTestBunchSize != null) { @@ -84,22 +79,24 @@ public class LoadRecentBranchRevisions extends TaskDescriptor { @Override public void run(ContinuationContext context) { final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); - final SvnCommittedChangesProvider committedChangesProvider = (SvnCommittedChangesProvider)myVcs.getCommittedChangesProvider(); + final SvnCommittedChangesProvider committedChangesProvider = + (SvnCommittedChangesProvider)myMergeContext.getVcs().getCommittedChangesProvider(); final ChangeBrowserSettings settings = new ChangeBrowserSettings(); if (myFirst > 0){ settings.CHANGE_BEFORE = String.valueOf(myFirst); settings.USE_CHANGE_BEFORE_FILTER = true; } - String local = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), myWcInfo.getRootUrl()); + String local = SVNPathUtil.getRelativePath(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getWcInfo().getRootUrl()); final String relativeLocal = (local.startsWith("/") ? local : "/" + local); - String relativeBranch = SVNPathUtil.getRelativePath(myWcInfo.getRepositoryRoot(), mySourceUrl); + String relativeBranch = SVNPathUtil.getRelativePath(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl()); relativeBranch = (relativeBranch.startsWith("/") ? relativeBranch : "/" + relativeBranch); - ProgressManager.progress2(SvnBundle.message("progress.text2.collecting.history", mySourceUrl + (myFirst > 0 ? ("@" + myFirst) : ""))); + ProgressManager.progress2( + SvnBundle.message("progress.text2.collecting.history", myMergeContext.getSourceUrl() + (myFirst > 0 ? ("@" + myFirst) : ""))); final List>> list = new ArrayList>>(); try { - committedChangesProvider.getCommittedChangesWithMergedRevisons(settings, new SvnRepositoryLocation(mySourceUrl), + committedChangesProvider.getCommittedChangesWithMergedRevisons(settings, new SvnRepositoryLocation(myMergeContext.getSourceUrl()), myBunchSize + (myFirst > 0 ? 2 : 1), new PairConsumer>() { public void consume(SvnChangeList svnList, TreeStructureNode tree) { @@ -123,7 +120,7 @@ public class LoadRecentBranchRevisions extends TaskDescriptor { } try { - myHelper = new OneShotMergeInfoHelper(myVcs.getProject(), myWcInfo, mySourceUrl); + myHelper = new OneShotMergeInfoHelper(myMergeContext.getProject(), myMergeContext.getWcInfo(), myMergeContext.getSourceUrl()); ProgressManager.progress2("Calculating not merged revisions"); myHelper.prepare(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java index b4f19ae1e912..1d5730ee7392 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeAllOrSelectedChooserTask.java @@ -40,9 +40,7 @@ public class MergeAllOrSelectedChooserTask extends BaseMergeTask { return; } if (QuickMergeContentsVariants.showLatest == variant) { - final LoadRecentBranchRevisions loader = - new LoadRecentBranchRevisions(myMergeContext.getBranchName(), -1, myMergeContext.getWcInfo(), myMergeContext - .getVcs(), myMergeContext.getSourceUrl()); + final LoadRecentBranchRevisions loader = new LoadRecentBranchRevisions(myMergeContext, -1); final ShowRecentInDialogTask dialog = new ShowRecentInDialogTask(myMergeContext, myInteraction, loader); context.next(loader, dialog); return; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShowRecentInDialogTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShowRecentInDialogTask.java index 5a094b700bbe..92277402747e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShowRecentInDialogTask.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ShowRecentInDialogTask.java @@ -58,9 +58,7 @@ public class ShowRecentInDialogTask extends BaseMergeTask { @Override public void consume(Long bunchSize, final MergeDialogI dialog) { final LoadRecentBranchRevisions loader = - new LoadRecentBranchRevisions( - myMergeContext.getBranchName(), dialog.getLastNumber(), myMergeContext.getWcInfo(), myMergeContext.getVcs(), - myMergeContext.getSourceUrl(), bunchSize.intValue()); + new LoadRecentBranchRevisions(myMergeContext, dialog.getLastNumber(), bunchSize.intValue()); final TaskDescriptor updater = new TaskDescriptor("", Where.AWT) { @Override public void run(ContinuationContext context) { From 4729cf2a2c2987e9365f115efebf379c9b26cbfb Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 21 Apr 2014 17:31:17 +0400 Subject: [PATCH 19/65] svn: Refactored OneShotMergeInfoHelper and OneRecursiveShotMergeInfoWorker - removed unnecessary fields and utilize MergeContext instead --- .../dialogs/LoadRecentBranchRevisions.java | 2 +- .../svn/integrate/MergeCalculatorTask.java | 2 +- .../OneRecursiveShotMergeInfoWorker.java | 31 +++++++++---------- .../svn/mergeinfo/OneShotMergeInfoHelper.java | 9 +++--- .../jetbrains/idea/svn/SvnMergeInfoTest.java | 6 +++- .../idea/svn16/SvnMergeInfoTest.java | 5 ++- 6 files changed, 30 insertions(+), 25 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java index a00cddf23ed2..880f6935d157 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java @@ -120,7 +120,7 @@ public class LoadRecentBranchRevisions extends TaskDescriptor { } try { - myHelper = new OneShotMergeInfoHelper(myMergeContext.getProject(), myMergeContext.getWcInfo(), myMergeContext.getSourceUrl()); + myHelper = new OneShotMergeInfoHelper(myMergeContext); ProgressManager.progress2("Calculating not merged revisions"); myHelper.prepare(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java index a534e34b1dff..9c880b6d3dda 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/MergeCalculatorTask.java @@ -78,7 +78,7 @@ public class MergeCalculatorTask extends BaseMergeTask implements myNotMerged = new LinkedList(); myMergeTitle = "Merge from " + myMergeContext.getBranchName(); // if (Boolean.TRUE.equals(Boolean.getBoolean(ourOneShotStrategy))) { - myMergeChecker = new OneShotMergeInfoHelper(myMergeContext.getProject(), myMergeContext.getWcInfo(), myMergeContext.getSourceUrl()); + myMergeChecker = new OneShotMergeInfoHelper(myMergeContext); ((OneShotMergeInfoHelper)myMergeChecker).prepare(); /* } else { myMergeChecker = new BranchInfo.MyMergeCheckerWrapper(myWcInfo.getPath(), new BranchInfo(myVcs, myWcInfo.getRepositoryRoot(), diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java index f492a434a252..bd2c41537091 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java @@ -15,15 +15,13 @@ */ package org.jetbrains.idea.svn.mergeinfo; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.AreaMap; import com.intellij.openapi.vcs.VcsException; import com.intellij.util.PairProcessor; -import org.jetbrains.idea.svn.SvnConfiguration; -import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.dialogs.WCInfo; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.dialogs.MergeContext; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNMergeInfoUtil; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; @@ -36,25 +34,25 @@ import java.io.File; import java.util.Map; public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker { - private final Project myProject; - private final WCInfo myWCInfo; + + @NotNull private final MergeContext myMergeContext; + // subpath [file] (local) to (subpathURL - merged FROM - to ranges list) private final AreaMap> myDataMap; private final Object myLock; private final String myFromUrlRelative; - public OneRecursiveShotMergeInfoWorker(final Project project, final WCInfo WCInfo, final String fromUrl) { - myProject = project; + public OneRecursiveShotMergeInfoWorker(@NotNull MergeContext mergeContext) { + myMergeContext = mergeContext; myLock = new Object(); - myWCInfo = WCInfo; - + myDataMap = AreaMap.create(new PairProcessor() { public boolean process(String parentUrl, String childUrl) { if (".".equals(parentUrl)) return true; return SVNPathUtil.isAncestor(ensureUrlFromSlash(parentUrl), ensureUrlFromSlash(childUrl)); } }); - final String url = SVNPathUtil.getRelativePath(myWCInfo.getRepositoryRoot(), fromUrl); + final String url = SVNPathUtil.getRelativePath(myMergeContext.getWcInfo().getRepositoryRoot(), myMergeContext.getSourceUrl()); myFromUrlRelative = ensureUrlFromSlash(url); } @@ -63,7 +61,7 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker { } public void prepare() throws VcsException { - final SVNDepth depth = SvnConfiguration.getInstance(myProject).isCheckNestedForQuickMerge() ? SVNDepth.INFINITY : SVNDepth.EMPTY; + final SVNDepth depth = myMergeContext.getVcs().getSvnConfiguration().isCheckNestedForQuickMerge() ? SVNDepth.INFINITY : SVNDepth.EMPTY; ISVNPropertyHandler handler = new ISVNPropertyHandler() { public void handleProperty(File path, SVNPropertyData property) throws SVNException { final String key = keyFromFile(path); @@ -80,10 +78,9 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker { } }; - final SvnVcs vcs = SvnVcs.getInstance(myProject); - File path = new File(myWCInfo.getPath()); + File path = new File(myMergeContext.getWcInfo().getPath()); - vcs.getFactory(path).createPropertyClient() + myMergeContext.getVcs().getFactory(path).createPropertyClient() .getProperty(SvnTarget.fromFile(path), SVNProperty.MERGE_INFO, SVNRevision.WORKING, depth, handler); } @@ -159,8 +156,8 @@ public class OneRecursiveShotMergeInfoWorker implements MergeInfoWorker { } private String keyFromFile(final File file) { - final String path = - FileUtil.getRelativePath(myWCInfo.getPath(), file.getAbsolutePath(), File.separatorChar).replace(File.separatorChar, '/'); + final String path = FileUtil.getRelativePath(myMergeContext.getWcInfo().getPath(), file.getAbsolutePath(), File.separatorChar).replace( + File.separatorChar, '/'); return keyFromPath(path); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java index 3b2f6b9c379a..72810b02b2de 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java @@ -15,19 +15,20 @@ */ package org.jetbrains.idea.svn.mergeinfo; -import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.VcsException; -import org.jetbrains.idea.svn.dialogs.WCInfo; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.dialogs.MergeContext; import org.jetbrains.idea.svn.history.SvnChangeList; import java.util.*; public class OneShotMergeInfoHelper implements MergeChecker { + private OneRecursiveShotMergeInfoWorker myWorker; private final Map> myPartiallyMerged; - public OneShotMergeInfoHelper(final Project project, final WCInfo wcInfo, final String branchPath) { - myWorker = new OneRecursiveShotMergeInfoWorker(project, wcInfo, branchPath); + public OneShotMergeInfoHelper(@NotNull MergeContext mergeContext) { + myWorker = new OneRecursiveShotMergeInfoWorker(mergeContext); myPartiallyMerged = new HashMap>(); } diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java index 4ecc1cbdd25e..05c382f9e8a2 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java @@ -24,6 +24,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.dialogs.MergeContext; import org.jetbrains.idea.svn.dialogs.WCInfo; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.history.SvnRepositoryLocation; @@ -35,6 +36,7 @@ import org.junit.Test; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.wc.SVNInfo; import org.tmatesoft.svn.core.wc.SVNPropertyData; import org.tmatesoft.svn.core.wc.SVNRevision; @@ -66,6 +68,7 @@ public class SvnMergeInfoTest extends Svn17TestCase { private String myTrunkUrl; private String myBranchUrl; + private MergeContext myMergeContext; @Override public void setUp() throws Exception { @@ -84,7 +87,8 @@ public class SvnMergeInfoTest extends Svn17TestCase { Node node = new Node(vcsRoot, SVNURL.parseURIEncoded(myBranchUrl), SVNURL.parseURIEncoded(myRepoUrl)); RootUrlInfo root = new RootUrlInfo(node, WorkingCopyFormat.ONE_DOT_SIX, vcsRoot, null); myWCInfo = new WCInfo(root, true, SVNDepth.INFINITY); - myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myProject, myWCInfo, myTrunkUrl); + myMergeContext = new MergeContext(SvnVcs.getInstance(myProject), myTrunkUrl, myWCInfo, SVNPathUtil.tail(myTrunkUrl), vcsRoot); + myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myMergeContext); myVcs = SvnVcs.getInstance(myProject); myVcs.getSvnConfiguration().setCheckNestedForQuickMerge(true); diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java index 73d273135e94..986ee0748b79 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java @@ -25,6 +25,7 @@ import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.dialogs.MergeContext; import org.jetbrains.idea.svn.dialogs.WCInfo; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.history.SvnRepositoryLocation; @@ -49,6 +50,7 @@ public class SvnMergeInfoTest extends Svn16TestCase { private ProjectLevelVcsManagerImpl myProjectLevelVcsManager; private WCInfo myWCInfo; private OneShotMergeInfoHelper myOneShotMergeInfoHelper; + private MergeContext myMergeContext; @Override public void setUp() throws Exception { @@ -64,7 +66,8 @@ public class SvnMergeInfoTest extends Svn16TestCase { Node node = new Node(vcsRoot, SVNURL.parseURIEncoded(myRepoUrl + "/branch"), SVNURL.parseURIEncoded(myRepoUrl)); RootUrlInfo root = new RootUrlInfo(node, WorkingCopyFormat.ONE_DOT_SIX, vcsRoot, null); myWCInfo = new WCInfo(root, true, SVNDepth.INFINITY); - myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myProject, myWCInfo, myRepoUrl + "/trunk"); + myMergeContext = new MergeContext(SvnVcs.getInstance(myProject), myRepoUrl + "/trunk", myWCInfo, "trunk", vcsRoot); + myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myMergeContext); SvnConfiguration.getInstance(myProject).setCheckNestedForQuickMerge(true); // AbstractVcs vcsFound = myProjectLevelVcsManager.findVcsByName(SvnVcs.VCS_NAME); From 626d944e277e07067c516f471d67bfa8d0308aca Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 23 Apr 2014 16:47:27 +0400 Subject: [PATCH 20/65] svn: Refactored SvnCheckinEnvironment - code simplified, unified code flows for SVNKit and command line --- .../svn/checkin/SvnCheckinEnvironment.java | 101 +++++++++--------- .../idea/svn/commandLine/SvnCommitRunner.java | 21 ++-- 2 files changed, 62 insertions(+), 60 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java index ccfb81efc98c..c288e8c132de 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java @@ -38,13 +38,17 @@ import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.*; +import com.intellij.util.ArrayUtil; +import com.intellij.util.FunctionUtil; +import com.intellij.util.NullableFunction; +import com.intellij.util.PairConsumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient; import org.jetbrains.idea.svn.commandLine.SvnCommitRunner; import org.tmatesoft.svn.core.SVNCommitInfo; @@ -126,7 +130,13 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { //noinspection unchecked final MultiMap,File> map = SvnUtil.splitIntoRepositoriesMap(mySvnVcs, committables, Convertor.SELF); for (Map.Entry, Collection> entry : map.entrySet()) { - doCommitOneRepo(entry.getValue(), committer, comment, force, exception, feedback, entry.getKey().getSecond()); + try { + doCommitOneRepo(entry.getValue(), committer, comment, force, exception, feedback, entry.getKey().getSecond()); + } + catch (VcsException e) { + LOG.info(e); + exception.add(e); + } } } @@ -134,52 +144,21 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { SVNCommitClient committer, String comment, boolean force, - List exception, final Set feedback, final WorkingCopyFormat format) { + List exception, final Set feedback, final WorkingCopyFormat format) + throws VcsException { if (committables.isEmpty()) { return; } // TODO: Create CommitClient and refactor to use common ClientFactory model. + SVNCommitInfo[] results; if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) || !WorkingCopyFormat.ONE_DOT_SIX.equals(format) && mySvnVcs.getSvnConfiguration().isCommandLine()) { - doWithCommandLine(committables, comment, exception, feedback); + results = doWithCommandLine(committables, comment); } else { - doWithSvnkit(committables, committer, comment, force, exception, feedback); + results = doWithSvnkit(committables, committer, comment, force); } - } - private void doWithSvnkit(Collection committables, - SVNCommitClient committer, - String comment, - boolean force, - List exception, Set feedback) { - File[] pathsToCommit = committables.toArray(new File[committables.size()]); - boolean keepLocks = SvnConfiguration.getInstance(mySvnVcs.getProject()).isKeepLocks(); - SVNCommitPacket[] commitPackets = null; - SVNCommitInfo[] results; - try { - commitPackets = committer.doCollectCommitItems(pathsToCommit, keepLocks, force, SVNDepth.EMPTY, true, null); - results = committer.doCommit(commitPackets, keepLocks, comment); - commitPackets = null; - } - catch (SVNException e) { - // exception on collecting commitables. - exception.add(new VcsException(e)); - LOG.info(e); - return; - } - finally { - if (commitPackets != null) { - for (SVNCommitPacket commitPacket : commitPackets) { - try { - commitPacket.dispose(); - } - catch (SVNException e) { - LOG.info(e); - } - } - } - } final StringBuilder committedRevisions = new StringBuilder(); for (SVNCommitInfo result : results) { if (result.getErrorMessage() != null) { @@ -197,29 +176,49 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { } } - private void doWithCommandLine(Collection committables, String comment, List exception, Set feedback) { + private SVNCommitInfo[] doWithSvnkit(Collection committables, SVNCommitClient committer, String comment, boolean force) + throws VcsException { + File[] pathsToCommit = committables.toArray(new File[committables.size()]); + boolean keepLocks = SvnConfiguration.getInstance(mySvnVcs.getProject()).isKeepLocks(); + SVNCommitPacket[] commitPackets = null; + SVNCommitInfo[] results; + try { + commitPackets = committer.doCollectCommitItems(pathsToCommit, keepLocks, force, SVNDepth.EMPTY, true, null); + results = committer.doCommit(commitPackets, keepLocks, comment); + commitPackets = null; + return results; + } + catch (SVNException e) { + throw new SvnBindException(e); + } + finally { + if (commitPackets != null) { + for (SVNCommitPacket commitPacket : commitPackets) { + try { + commitPacket.dispose(); + } + catch (SVNException e) { + LOG.info(e); + } + } + } + } + } + + private SVNCommitInfo[] doWithCommandLine(Collection committables, String comment) throws VcsException { // if directory renames were used, IDEA reports all files under them as moved, but for svn we can not pass some of them // to commit command - since not all paths are registered as changes -> so we need to filter these cases, but only if // there at least some child-parent relationships in passed paths try { committables = filterCommittables(committables); } catch (SVNException e) { - exception.add(new VcsException(e)); - return; + throw new SvnBindException(e); } IdeaCommitHandler handler = new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator()); + SvnCommitRunner runner = new SvnCommitRunner(mySvnVcs, handler); - try { - SvnCommitRunner runner = new SvnCommitRunner(mySvnVcs, handler); - final long revision = - runner.commit(ArrayUtil.toObjectArray(committables, File.class), comment, SVNDepth.EMPTY, false, false, null, null); - - reportCommittedRevisions(feedback, String.valueOf(revision)); - } - catch (VcsException e) { - exception.add(e); - } + return runner.commit(ArrayUtil.toObjectArray(committables, File.class), comment, SVNDepth.EMPTY, false, false, null, null); } private Collection filterCommittables(Collection committables) throws SVNException { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java index d9b760d8b24a..c68567a48429 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java @@ -23,6 +23,7 @@ import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; +import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -51,14 +52,14 @@ public class SvnCommitRunner { myCommandListener = new CommandListener(handler); } - public long commit(File[] paths, - String message, - @Nullable SVNDepth depth, - boolean noUnlock, - boolean keepChangelist, - Collection changelists, - Map revpropTable) throws VcsException { - if (paths.length == 0) return INVALID_REVISION_NUMBER; + public SVNCommitInfo[] commit(File[] paths, + String message, + @Nullable SVNDepth depth, + boolean noUnlock, + boolean keepChangelist, + Collection changelists, + Map revpropTable) throws VcsException { + if (paths.length == 0) return new SVNCommitInfo[]{SVNCommitInfo.NULL}; final List parameters = new ArrayList(); CommandUtil.put(parameters, depth); @@ -83,7 +84,9 @@ public class SvnCommitRunner { CommandUtil.execute(myVcs, SvnTarget.fromFile(paths[0]), SvnCommandName.ci, parameters, myCommandListener); myCommandListener.throwExceptionIfOccurred(); - return validateRevisionNumber(); + long revision = validateRevisionNumber(); + + return new SVNCommitInfo[]{new SVNCommitInfo(revision, null, null, null)}; } private long validateRevisionNumber() throws VcsException { From beb808118761726a49d857a0382ce8ff84444aae Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 23 Apr 2014 17:29:00 +0400 Subject: [PATCH 21/65] svn: Refactored SvnCheckinEnvironment - moved SVNKit related logic to corresponding SVNKit-scoped method --- .../svn/checkin/SvnCheckinEnvironment.java | 58 ++++++++----------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java index c288e8c132de..9c48372b03b7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java @@ -87,51 +87,34 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { return null; } - - private List commitInt(List paths, final String comment, final boolean force, final Set feedback) { + private List commitInt(List paths, final String comment, final Set feedback) { final List exception = new ArrayList(); final List committables = getCommitables(paths); - - final SVNCommitClient committer = mySvnVcs.createCommitClient(); - final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); - IdeaCommitHandler handler = new IdeaCommitHandler(progress, true, true); - if (progress != null) { - committer.setEventHandler(handler); - } if (progress != null) { - doCommit(committables, committer, comment, force, exception, feedback); + doCommit(committables, comment, exception, feedback); } else if (ApplicationManager.getApplication().isDispatchThread()) { ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { public void run() { - doCommit(committables, committer, comment, force, exception, feedback); + doCommit(committables, comment, exception, feedback); } }, SvnBundle.message("progress.title.commit"), false, mySvnVcs.getProject()); } else { - doCommit(committables, committer, comment, force, exception, feedback); + doCommit(committables, comment, exception, feedback); } - // TODO: Check if such processing of deleted files also necessary for command line. And if yes - use one handler instance for both - // TODO: SVNKit and command line code flows. - for(VirtualFile f : handler.getDeletedFiles()) { - f.putUserData(VirtualFile.REQUESTOR_MARKER, this); - } return exception; } - private void doCommit(List committables, - SVNCommitClient committer, - String comment, - boolean force, - List exception, final Set feedback) { + private void doCommit(List committables, String comment, List exception, final Set feedback) { //noinspection unchecked final MultiMap,File> map = SvnUtil.splitIntoRepositoriesMap(mySvnVcs, committables, Convertor.SELF); for (Map.Entry, Collection> entry : map.entrySet()) { try { - doCommitOneRepo(entry.getValue(), committer, comment, force, exception, feedback, entry.getKey().getSecond()); + doCommitOneRepo(entry.getValue(), comment, exception, feedback, entry.getKey().getSecond()); } catch (VcsException e) { LOG.info(e); @@ -141,11 +124,11 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { } private void doCommitOneRepo(Collection committables, - SVNCommitClient committer, String comment, - boolean force, - List exception, final Set feedback, final WorkingCopyFormat format) - throws VcsException { + List exception, + final Set feedback, + final WorkingCopyFormat format) + throws VcsException { if (committables.isEmpty()) { return; } @@ -156,7 +139,7 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { results = doWithCommandLine(committables, comment); } else { - results = doWithSvnkit(committables, committer, comment, force); + results = doWithSvnkit(committables, comment); } final StringBuilder committedRevisions = new StringBuilder(); @@ -176,17 +159,19 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { } } - private SVNCommitInfo[] doWithSvnkit(Collection committables, SVNCommitClient committer, String comment, boolean force) - throws VcsException { + private SVNCommitInfo[] doWithSvnkit(Collection committables, String comment) throws VcsException { File[] pathsToCommit = committables.toArray(new File[committables.size()]); boolean keepLocks = SvnConfiguration.getInstance(mySvnVcs.getProject()).isKeepLocks(); SVNCommitPacket[] commitPackets = null; SVNCommitInfo[] results; + SVNCommitClient committer = mySvnVcs.createCommitClient(); + IdeaCommitHandler handler = new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator(), true, true); + + committer.setEventHandler(handler); try { - commitPackets = committer.doCollectCommitItems(pathsToCommit, keepLocks, force, SVNDepth.EMPTY, true, null); + commitPackets = committer.doCollectCommitItems(pathsToCommit, keepLocks, true, SVNDepth.EMPTY, true, null); results = committer.doCommit(commitPackets, keepLocks, comment); commitPackets = null; - return results; } catch (SVNException e) { throw new SvnBindException(e); @@ -203,6 +188,13 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { } } } + + // This seems to be necessary only for SVNKit as changes after command line operations should be detected during VFS refresh. + for(VirtualFile f : handler.getDeletedFiles()) { + f.putUserData(VirtualFile.REQUESTOR_MARKER, this); + } + + return results; } private SVNCommitInfo[] doWithCommandLine(Collection committables, String comment) throws VcsException { @@ -371,7 +363,7 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { String preparedComment, @NotNull NullableFunction parametersHolder, Set feedback) { - return commitInt(collectPaths(changes), preparedComment, true, feedback); + return commitInt(collectPaths(changes), preparedComment, feedback); } public List commit(List changes, String preparedComment) { From af5ad7c813494ba7c8ff75438cc304521d100b62 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 23 Apr 2014 18:28:01 +0400 Subject: [PATCH 22/65] svn: Refactored SvnCommitRunner - inlined several parameters (that have same value in all code paths) --- .../svn/checkin/SvnCheckinEnvironment.java | 2 +- .../idea/svn/commandLine/SvnCommitRunner.java | 23 ++++--------------- 2 files changed, 6 insertions(+), 19 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java index 9c48372b03b7..c7122f8897b1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java @@ -210,7 +210,7 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { IdeaCommitHandler handler = new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator()); SvnCommitRunner runner = new SvnCommitRunner(mySvnVcs, handler); - return runner.commit(ArrayUtil.toObjectArray(committables, File.class), comment, SVNDepth.EMPTY, false, false, null, null); + return runner.commit(ArrayUtil.toObjectArray(committables, File.class), comment); } private Collection filterCommittables(Collection committables) throws SVNException { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java index c68567a48429..cf0ddfc864a1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java @@ -52,28 +52,15 @@ public class SvnCommitRunner { myCommandListener = new CommandListener(handler); } - public SVNCommitInfo[] commit(File[] paths, - String message, - @Nullable SVNDepth depth, - boolean noUnlock, - boolean keepChangelist, - Collection changelists, - Map revpropTable) throws VcsException { + public SVNCommitInfo[] commit(File[] paths, String message) throws VcsException { if (paths.length == 0) return new SVNCommitInfo[]{SVNCommitInfo.NULL}; final List parameters = new ArrayList(); - CommandUtil.put(parameters, depth); - CommandUtil.put(parameters, noUnlock, "--no-unlock"); - CommandUtil.put(parameters, keepChangelist, "--keep-changelists"); - CommandUtil.putChangeLists(parameters, changelists); + CommandUtil.put(parameters, SVNDepth.EMPTY); + CommandUtil.put(parameters, false, "--no-unlock"); + CommandUtil.put(parameters, false, "--keep-changelists"); + CommandUtil.putChangeLists(parameters, null); - if (revpropTable != null && ! revpropTable.isEmpty()) { - final Set> set = revpropTable.entrySet(); - for (Map.Entry entry : set) { - parameters.add("--with-revprop"); - parameters.add(entry.getKey() + "=" + entry.getValue()); - } - } parameters.add("-m"); parameters.add(message); // TODO: seems that sort is not necessary here From b0b7121f7d80a5d7a9c05dfc2867108a114b9d69 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 23 Apr 2014 18:38:52 +0400 Subject: [PATCH 23/65] svn: Refactored SvnCheckinEnvironment - logic extracted to separate SVNKit and command line clients (common client factory model is used) --- .../src/org/jetbrains/idea/svn/SvnVcs.java | 6 +- .../jetbrains/idea/svn/api/ClientFactory.java | 9 +- .../idea/svn/api/CmdClientFactory.java | 8 +- .../idea/svn/api/SvnKitClientFactory.java | 6 +- .../idea/svn/checkin/CheckinClient.java | 33 +++++ .../svn/checkin/SvnCheckinEnvironment.java | 122 +----------------- .../idea/svn/checkin/SvnKitCheckinClient.java | 81 ++++++++++++ .../idea/svn/commandLine/SvnCommitRunner.java | 96 +++++++++++--- 8 files changed, 223 insertions(+), 138 deletions(-) create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CheckinClient.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitCheckinClient.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index 89a1eef5f47b..ba425af47f26 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -84,7 +84,6 @@ import org.jetbrains.idea.svn.history.SvnCommittedChangesProvider; import org.jetbrains.idea.svn.history.SvnHistoryProvider; import org.jetbrains.idea.svn.lowLevel.PrimitivePool; import org.jetbrains.idea.svn.networking.SSLProtocolExceptionParser; -import org.jetbrains.idea.svn.portable.SvnWcClientI; import org.jetbrains.idea.svn.properties.PropertyClient; import org.jetbrains.idea.svn.rollback.SvnRollbackEnvironment; import org.jetbrains.idea.svn.update.SvnIntegrateEnvironment; @@ -1386,6 +1385,11 @@ public class SvnVcs extends AbstractVcs { return getFactory(getProjectRootFormat(), false); } + @NotNull + public ClientFactory getFactory(@NotNull WorkingCopyFormat format) { + return getFactory(format, false); + } + public ClientFactory getSvnKitFactory() { return svnKitClientFactory; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java index 9c01217da9f1..441399fab0a4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java @@ -6,6 +6,7 @@ import org.jetbrains.idea.svn.add.AddClient; import org.jetbrains.idea.svn.annotate.AnnotateClient; import org.jetbrains.idea.svn.browse.BrowseClient; import org.jetbrains.idea.svn.change.ChangeListClient; +import org.jetbrains.idea.svn.checkin.CheckinClient; import org.jetbrains.idea.svn.checkin.ImportClient; import org.jetbrains.idea.svn.checkout.CheckoutClient; import org.jetbrains.idea.svn.checkout.ExportClient; @@ -19,11 +20,11 @@ import org.jetbrains.idea.svn.history.HistoryClient; import org.jetbrains.idea.svn.integrate.MergeClient; import org.jetbrains.idea.svn.lock.LockClient; import org.jetbrains.idea.svn.portable.SvnStatusClientI; -import org.jetbrains.idea.svn.update.UpdateClient; import org.jetbrains.idea.svn.portable.SvnWcClientI; import org.jetbrains.idea.svn.properties.PropertyClient; import org.jetbrains.idea.svn.revert.RevertClient; import org.jetbrains.idea.svn.update.RelocateClient; +import org.jetbrains.idea.svn.update.UpdateClient; import org.jetbrains.idea.svn.upgrade.UpgradeClient; /** @@ -57,6 +58,7 @@ public abstract class ClientFactory { protected UpgradeClient myUpgradeClient; protected BrowseClient myBrowseClient; protected DiffClient myDiffClient; + protected CheckinClient myCheckinClient; protected ClientFactory(@NotNull SvnVcs vcs) { myVcs = vcs; @@ -187,6 +189,11 @@ public abstract class ClientFactory { return prepare(myDiffClient); } + @NotNull + public CheckinClient createCheckinClient() { + return prepare(myCheckinClient); + } + @NotNull protected T prepare(@NotNull T client) { client.setVcs(myVcs); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java index 653852ca3f49..e18af3c2a5a0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java @@ -10,21 +10,22 @@ import org.jetbrains.idea.svn.checkin.CmdImportClient; import org.jetbrains.idea.svn.checkout.CmdCheckoutClient; import org.jetbrains.idea.svn.checkout.CmdExportClient; import org.jetbrains.idea.svn.cleanup.CmdCleanupClient; -import org.jetbrains.idea.svn.diff.CmdDiffClient; -import org.jetbrains.idea.svn.update.CmdUpdateClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient; +import org.jetbrains.idea.svn.commandLine.SvnCommitRunner; import org.jetbrains.idea.svn.conflict.CmdConflictClient; import org.jetbrains.idea.svn.content.CmdContentClient; import org.jetbrains.idea.svn.copy.CmdCopyMoveClient; import org.jetbrains.idea.svn.delete.CmdDeleteClient; +import org.jetbrains.idea.svn.diff.CmdDiffClient; import org.jetbrains.idea.svn.history.CmdHistoryClient; import org.jetbrains.idea.svn.integrate.CmdMergeClient; import org.jetbrains.idea.svn.lock.CmdLockClient; -import org.jetbrains.idea.svn.update.UpdateClient; import org.jetbrains.idea.svn.properties.CmdPropertyClient; import org.jetbrains.idea.svn.revert.CmdRevertClient; import org.jetbrains.idea.svn.update.CmdRelocateClient; +import org.jetbrains.idea.svn.update.CmdUpdateClient; +import org.jetbrains.idea.svn.update.UpdateClient; import org.jetbrains.idea.svn.upgrade.CmdUpgradeClient; /** @@ -59,6 +60,7 @@ public class CmdClientFactory extends ClientFactory { myUpgradeClient = new CmdUpgradeClient(); myBrowseClient = new CmdBrowseClient(); myDiffClient = new CmdDiffClient(); + myCheckinClient = new SvnCommitRunner(); statusClient = new SvnCommandLineStatusClient(myVcs); infoClient = new SvnCommandLineInfoClient(myVcs); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java index 3fb1d83c159d..95cfe0c224f7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java @@ -6,6 +6,7 @@ import org.jetbrains.idea.svn.add.SvnKitAddClient; import org.jetbrains.idea.svn.annotate.SvnKitAnnotateClient; import org.jetbrains.idea.svn.browse.SvnKitBrowseClient; import org.jetbrains.idea.svn.change.SvnKitChangeListClient; +import org.jetbrains.idea.svn.checkin.SvnKitCheckinClient; import org.jetbrains.idea.svn.checkin.SvnKitImportClient; import org.jetbrains.idea.svn.checkout.SvnKitCheckoutClient; import org.jetbrains.idea.svn.checkout.SvnKitExportClient; @@ -18,13 +19,13 @@ import org.jetbrains.idea.svn.diff.SvnKitDiffClient; import org.jetbrains.idea.svn.history.SvnKitHistoryClient; import org.jetbrains.idea.svn.integrate.SvnKitMergeClient; import org.jetbrains.idea.svn.lock.SvnKitLockClient; -import org.jetbrains.idea.svn.update.SvnKitUpdateClient; -import org.jetbrains.idea.svn.update.UpdateClient; import org.jetbrains.idea.svn.portable.SvnkitSvnStatusClient; import org.jetbrains.idea.svn.portable.SvnkitSvnWcClient; import org.jetbrains.idea.svn.properties.SvnKitPropertyClient; import org.jetbrains.idea.svn.revert.SvnKitRevertClient; import org.jetbrains.idea.svn.update.SvnKitRelocateClient; +import org.jetbrains.idea.svn.update.SvnKitUpdateClient; +import org.jetbrains.idea.svn.update.UpdateClient; import org.jetbrains.idea.svn.upgrade.SvnKitUpgradeClient; /** @@ -59,6 +60,7 @@ public class SvnKitClientFactory extends ClientFactory { myUpgradeClient = new SvnKitUpgradeClient(); myBrowseClient = new SvnKitBrowseClient(); myDiffClient = new SvnKitDiffClient(); + myCheckinClient = new SvnKitCheckinClient(); statusClient = new SvnkitSvnStatusClient(myVcs, null); infoClient = new SvnkitSvnWcClient(myVcs); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CheckinClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CheckinClient.java new file mode 100644 index 000000000000..628c22219e11 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CheckinClient.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.checkin; + +import com.intellij.openapi.vcs.VcsException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.api.SvnClient; +import org.tmatesoft.svn.core.SVNCommitInfo; + +import java.io.File; +import java.util.Collection; + +/** + * @author Konstantin Kolosovsky. + */ +public interface CheckinClient extends SvnClient { + + @NotNull + SVNCommitInfo[] commit(@NotNull Collection paths, @NotNull String comment) throws VcsException; +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java index c7122f8897b1..6fb1b95b7afe 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java @@ -24,8 +24,6 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.vcs.AbstractFilterChildren; import com.intellij.openapi.vcs.CheckinProjectPanel; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; @@ -38,7 +36,6 @@ import com.intellij.openapi.vcs.ui.RefreshableOnComponent; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.ArrayUtil; import com.intellij.util.FunctionUtil; import com.intellij.util.NullableFunction; import com.intellij.util.PairConsumer; @@ -48,14 +45,14 @@ import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; -import org.jetbrains.idea.svn.commandLine.SvnBindException; -import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient; -import org.jetbrains.idea.svn.commandLine.SvnCommitRunner; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.ISVNEventHandler; +import org.tmatesoft.svn.core.wc.SVNEvent; +import org.tmatesoft.svn.core.wc.SVNStatus; +import org.tmatesoft.svn.core.wc.SVNStatusType; import javax.swing.*; import java.awt.*; @@ -132,15 +129,8 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { if (committables.isEmpty()) { return; } - // TODO: Create CommitClient and refactor to use common ClientFactory model. - SVNCommitInfo[] results; - if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format) || - !WorkingCopyFormat.ONE_DOT_SIX.equals(format) && mySvnVcs.getSvnConfiguration().isCommandLine()) { - results = doWithCommandLine(committables, comment); - } - else { - results = doWithSvnkit(committables, comment); - } + + SVNCommitInfo[] results = mySvnVcs.getFactory(format).createCheckinClient().commit(committables, comment); final StringBuilder committedRevisions = new StringBuilder(); for (SVNCommitInfo result : results) { @@ -159,106 +149,6 @@ public class SvnCheckinEnvironment implements CheckinEnvironment { } } - private SVNCommitInfo[] doWithSvnkit(Collection committables, String comment) throws VcsException { - File[] pathsToCommit = committables.toArray(new File[committables.size()]); - boolean keepLocks = SvnConfiguration.getInstance(mySvnVcs.getProject()).isKeepLocks(); - SVNCommitPacket[] commitPackets = null; - SVNCommitInfo[] results; - SVNCommitClient committer = mySvnVcs.createCommitClient(); - IdeaCommitHandler handler = new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator(), true, true); - - committer.setEventHandler(handler); - try { - commitPackets = committer.doCollectCommitItems(pathsToCommit, keepLocks, true, SVNDepth.EMPTY, true, null); - results = committer.doCommit(commitPackets, keepLocks, comment); - commitPackets = null; - } - catch (SVNException e) { - throw new SvnBindException(e); - } - finally { - if (commitPackets != null) { - for (SVNCommitPacket commitPacket : commitPackets) { - try { - commitPacket.dispose(); - } - catch (SVNException e) { - LOG.info(e); - } - } - } - } - - // This seems to be necessary only for SVNKit as changes after command line operations should be detected during VFS refresh. - for(VirtualFile f : handler.getDeletedFiles()) { - f.putUserData(VirtualFile.REQUESTOR_MARKER, this); - } - - return results; - } - - private SVNCommitInfo[] doWithCommandLine(Collection committables, String comment) throws VcsException { - // if directory renames were used, IDEA reports all files under them as moved, but for svn we can not pass some of them - // to commit command - since not all paths are registered as changes -> so we need to filter these cases, but only if - // there at least some child-parent relationships in passed paths - try { - committables = filterCommittables(committables); - } catch (SVNException e) { - throw new SvnBindException(e); - } - - IdeaCommitHandler handler = new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator()); - SvnCommitRunner runner = new SvnCommitRunner(mySvnVcs, handler); - - return runner.commit(ArrayUtil.toObjectArray(committables, File.class), comment); - } - - private Collection filterCommittables(Collection committables) throws SVNException { - final Set childrenOfSomebody = ContainerUtil.newHashSet(); - new AbstractFilterChildren() { - @Override - protected void sortAscending(List list) { - Collections.sort(list); - } - - @Override - protected boolean isAncestor(File parent, File child) { - // strict here will ensure that for case insensitive file systems paths different only by case will not be treated as ancestors - // of each other which is what we need to perform renames from one case to another on Windows - final boolean isAncestor = FileUtil.isAncestor(parent, child, true); - if (isAncestor) { - childrenOfSomebody.add(child.getPath()); - } - return isAncestor; - } - }.doFilter(new ArrayList(committables)); - if (! childrenOfSomebody.isEmpty()) { - List result = ContainerUtil.newArrayList(); - SvnCommandLineStatusClient statusClient = new SvnCommandLineStatusClient(mySvnVcs); - - for (File file : committables) { - if (!childrenOfSomebody.contains(file.getPath())) { - result.add(file); - } else { - try { - final SVNStatus status = statusClient.doStatus(file, false); - if (status != null && ! SVNStatusType.STATUS_NONE.equals(status.getContentsStatus()) && - ! SVNStatusType.STATUS_UNVERSIONED.equals(status.getContentsStatus())) { - result.add(file); - } - } - catch (SVNException e) { - // not versioned - LOG.info(e); - throw e; - } - } - } - return result; - } - return committables; - } - private void reportCommittedRevisions(Set feedback, String committedRevisions) { final Project project = mySvnVcs.getProject(); final String message = SvnBundle.message("status.text.comitted.revision", committedRevisions); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitCheckinClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitCheckinClient.java new file mode 100644 index 000000000000..9cd423cd530b --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitCheckinClient.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.checkin; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.tmatesoft.svn.core.SVNCommitInfo; +import org.tmatesoft.svn.core.SVNDepth; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.wc.SVNCommitClient; +import org.tmatesoft.svn.core.wc.SVNCommitPacket; + +import java.io.File; +import java.util.Collection; + +/** + * @author Konstantin Kolosovsky. + */ +public class SvnKitCheckinClient extends BaseSvnClient implements CheckinClient { + + private static final Logger LOG = Logger.getInstance(SvnKitCheckinClient.class); + + @NotNull + @Override + public SVNCommitInfo[] commit(@NotNull Collection paths, @NotNull String comment) throws VcsException { + File[] pathsToCommit = ArrayUtil.toObjectArray(paths, File.class); + boolean keepLocks = myVcs.getSvnConfiguration().isKeepLocks(); + SVNCommitPacket[] commitPackets = null; + SVNCommitInfo[] results; + SVNCommitClient committer = myVcs.createCommitClient(); + IdeaCommitHandler handler = new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator(), true, true); + + committer.setEventHandler(handler); + try { + commitPackets = committer.doCollectCommitItems(pathsToCommit, keepLocks, true, SVNDepth.EMPTY, true, null); + results = committer.doCommit(commitPackets, keepLocks, comment); + commitPackets = null; + } + catch (SVNException e) { + throw new SvnBindException(e); + } + finally { + if (commitPackets != null) { + for (SVNCommitPacket commitPacket : commitPackets) { + try { + commitPacket.dispose(); + } + catch (SVNException e) { + LOG.info(e); + } + } + } + } + + // This seems to be necessary only for SVNKit as changes after command line operations should be detected during VFS refresh. + for (VirtualFile f : handler.getDeletedFiles()) { + f.putUserData(VirtualFile.REQUESTOR_MARKER, this); + } + + return results; + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java index cf0ddfc864a1..eefd222585d8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java @@ -17,14 +17,24 @@ package org.jetbrains.idea.svn.commandLine; import com.intellij.execution.process.ProcessOutputTypes; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vcs.AbstractFilterChildren; import com.intellij.openapi.vcs.VcsException; +import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.jetbrains.idea.svn.checkin.CheckinClient; +import org.jetbrains.idea.svn.checkin.IdeaCommitHandler; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.wc.SVNStatus; +import org.tmatesoft.svn.core.wc.SVNStatusType; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; @@ -38,21 +48,30 @@ import java.util.regex.Pattern; * Date: 2/25/13 * Time: 4:56 PM */ -public class SvnCommitRunner { +public class SvnCommitRunner extends BaseSvnClient implements CheckinClient { private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.commandLine.SvnCommitRunner"); public static final long INVALID_REVISION_NUMBER = -1L; - private SvnCommitRunner.CommandListener myCommandListener; - private SvnVcs myVcs; + @NotNull + @Override + public SVNCommitInfo[] commit(@NotNull Collection paths, @NotNull String message) throws VcsException { + // if directory renames were used, IDEA reports all files under them as moved, but for svn we can not pass some of them + // to commit command - since not all paths are registered as changes -> so we need to filter these cases, but only if + // there at least some child-parent relationships in passed paths + try { + paths = filterCommittables(paths); + } + catch (SVNException e) { + throw new SvnBindException(e); + } - public SvnCommitRunner(@NotNull SvnVcs vcs, @Nullable CommitEventHandler handler) { - myVcs = vcs; - myCommandListener = new CommandListener(handler); + return commit(ArrayUtil.toObjectArray(paths, File.class), message); } - public SVNCommitInfo[] commit(File[] paths, String message) throws VcsException { + @NotNull + public SVNCommitInfo[] commit(@NotNull File[] paths, @NotNull String message) throws VcsException { if (paths.length == 0) return new SVNCommitInfo[]{SVNCommitInfo.NULL}; final List parameters = new ArrayList(); @@ -67,18 +86,18 @@ public class SvnCommitRunner { Arrays.sort(paths); CommandUtil.put(parameters, paths); - myCommandListener.setBaseDirectory(CommandUtil.correctUpToExistingParent(paths[0])); - CommandUtil.execute(myVcs, SvnTarget.fromFile(paths[0]), SvnCommandName.ci, parameters, myCommandListener); - myCommandListener.throwExceptionIfOccurred(); + IdeaCommitHandler handler = new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator()); + SvnCommitRunner.CommandListener listener = new CommandListener(handler); + listener.setBaseDirectory(CommandUtil.correctUpToExistingParent(paths[0])); + CommandUtil.execute(myVcs, SvnTarget.fromFile(paths[0]), SvnCommandName.ci, parameters, listener); + listener.throwExceptionIfOccurred(); - long revision = validateRevisionNumber(); + long revision = validateRevisionNumber(listener.getCommittedRevision()); return new SVNCommitInfo[]{new SVNCommitInfo(revision, null, null, null)}; } - private long validateRevisionNumber() throws VcsException { - long revision = myCommandListener.getCommittedRevision(); - + private static long validateRevisionNumber(long revision) throws VcsException { if (revision < 0) { throw new VcsException("Wrong committed revision number: " + revision); } @@ -86,6 +105,53 @@ public class SvnCommitRunner { return revision; } + private Collection filterCommittables(@NotNull Collection committables) throws SVNException { + final Set childrenOfSomebody = ContainerUtil.newHashSet(); + new AbstractFilterChildren() { + @Override + protected void sortAscending(List list) { + Collections.sort(list); + } + + @Override + protected boolean isAncestor(File parent, File child) { + // strict here will ensure that for case insensitive file systems paths different only by case will not be treated as ancestors + // of each other which is what we need to perform renames from one case to another on Windows + final boolean isAncestor = FileUtil.isAncestor(parent, child, true); + if (isAncestor) { + childrenOfSomebody.add(child.getPath()); + } + return isAncestor; + } + }.doFilter(ContainerUtil.newArrayList(committables)); + if (!childrenOfSomebody.isEmpty()) { + List result = ContainerUtil.newArrayList(); + SvnCommandLineStatusClient statusClient = new SvnCommandLineStatusClient(myVcs); + + for (File file : committables) { + if (!childrenOfSomebody.contains(file.getPath())) { + result.add(file); + } + else { + try { + final SVNStatus status = statusClient.doStatus(file, false); + if (status != null && !SVNStatusType.STATUS_NONE.equals(status.getContentsStatus()) && + !SVNStatusType.STATUS_UNVERSIONED.equals(status.getContentsStatus())) { + result.add(file); + } + } + catch (SVNException e) { + // not versioned + LOG.info(e); + throw e; + } + } + } + return result; + } + return committables; + } + public static class CommandListener extends LineCommandAdapter { // Status could contain spaces, like "Adding copy of ". But at the end we are not interested in "copy of" part and want to have From 82af9cbc7fbb3040fe65efd3faaf02f3f2f5d2de Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 23 Apr 2014 19:29:23 +0400 Subject: [PATCH 24/65] svn: SvnCommitRunner moved to "checkin" package and renamed --- .../org/jetbrains/idea/svn/api/CmdClientFactory.java | 4 ++-- .../CmdCheckinClient.java} | 11 +++++------ .../jetbrains/idea/svn/checkin/CmdImportClient.java | 3 +-- .../jetbrains/idea/svn/copy/CmdCopyMoveClient.java | 3 ++- 4 files changed, 10 insertions(+), 11 deletions(-) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{commandLine/SvnCommitRunner.java => checkin/CmdCheckinClient.java} (96%) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java index e18af3c2a5a0..601b3d170600 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java @@ -12,7 +12,7 @@ import org.jetbrains.idea.svn.checkout.CmdExportClient; import org.jetbrains.idea.svn.cleanup.CmdCleanupClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient; -import org.jetbrains.idea.svn.commandLine.SvnCommitRunner; +import org.jetbrains.idea.svn.checkin.CmdCheckinClient; import org.jetbrains.idea.svn.conflict.CmdConflictClient; import org.jetbrains.idea.svn.content.CmdContentClient; import org.jetbrains.idea.svn.copy.CmdCopyMoveClient; @@ -60,7 +60,7 @@ public class CmdClientFactory extends ClientFactory { myUpgradeClient = new CmdUpgradeClient(); myBrowseClient = new CmdBrowseClient(); myDiffClient = new CmdDiffClient(); - myCheckinClient = new SvnCommitRunner(); + myCheckinClient = new CmdCheckinClient(); statusClient = new SvnCommandLineStatusClient(myVcs); infoClient = new SvnCommandLineInfoClient(myVcs); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java similarity index 96% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java index eefd222585d8..0e43b4afcde6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.commandLine; +package org.jetbrains.idea.svn.checkin; import com.intellij.execution.process.ProcessOutputTypes; import com.intellij.openapi.diagnostic.Logger; @@ -28,8 +28,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; -import org.jetbrains.idea.svn.checkin.CheckinClient; -import org.jetbrains.idea.svn.checkin.IdeaCommitHandler; +import org.jetbrains.idea.svn.commandLine.*; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; @@ -48,9 +47,9 @@ import java.util.regex.Pattern; * Date: 2/25/13 * Time: 4:56 PM */ -public class SvnCommitRunner extends BaseSvnClient implements CheckinClient { +public class CmdCheckinClient extends BaseSvnClient implements CheckinClient { - private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.commandLine.SvnCommitRunner"); + private static final Logger LOG = Logger.getInstance(CmdCheckinClient.class); public static final long INVALID_REVISION_NUMBER = -1L; @@ -87,7 +86,7 @@ public class SvnCommitRunner extends BaseSvnClient implements CheckinClient { CommandUtil.put(parameters, paths); IdeaCommitHandler handler = new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator()); - SvnCommitRunner.CommandListener listener = new CommandListener(handler); + CmdCheckinClient.CommandListener listener = new CommandListener(handler); listener.setBaseDirectory(CommandUtil.correctUpToExistingParent(paths[0])); CommandUtil.execute(myVcs, SvnTarget.fromFile(paths[0]), SvnCommandName.ci, parameters, listener); listener.throwExceptionIfOccurred(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java index d6cb8945932e..e78cf6aa0428 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java @@ -7,7 +7,6 @@ import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.jetbrains.idea.svn.commandLine.CommitEventHandler; import org.jetbrains.idea.svn.commandLine.SvnCommandName; -import org.jetbrains.idea.svn.commandLine.SvnCommitRunner; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.ISVNCommitHandler; @@ -41,7 +40,7 @@ public class CmdImportClient extends BaseSvnClient implements ImportClient { parameters.add("--message"); parameters.add(message); - SvnCommitRunner.CommandListener listener = new SvnCommitRunner.CommandListener(handler); + CmdCheckinClient.CommandListener listener = new CmdCheckinClient.CommandListener(handler); listener.setBaseDirectory(path); CommandUtil.execute(myVcs, SvnTarget.fromURL(url), SvnCommandName.importFolder, parameters, listener); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java index 832141d254f8..692724dd72e8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java @@ -6,6 +6,7 @@ import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.jetbrains.idea.svn.checkin.CmdCheckinClient; import org.jetbrains.idea.svn.commandLine.*; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNRevision; @@ -61,7 +62,7 @@ public class CmdCopyMoveClient extends BaseSvnClient implements CopyMoveClient { // copy to url output is the same as commit output - just statuses have "copy of" suffix // so "Adding" will be "Adding copy of" - SvnCommitRunner.CommandListener listener = new SvnCommitRunner.CommandListener(handler); + CmdCheckinClient.CommandListener listener = new CmdCheckinClient.CommandListener(handler); // TODO: Check correctness when source is url if (source.isFile()) { listener.setBaseDirectory(source.getFile()); From 416463d7a48e7947636fd37141c01ee76989e123 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 23 Apr 2014 20:48:27 +0400 Subject: [PATCH 25/65] svn: Refactored SvnRecursiveStatusWalker.MyItem.getClient() - removed unnecessary parameters --- .../jetbrains/idea/svn/SvnRecursiveStatusWalker.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java index 741de4f6c2d7..b311921a81ec 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java @@ -75,7 +75,7 @@ public class SvnRecursiveStatusWalker { if (path.isDirectory()) { myHandler.setCurrentItem(item); try { - final SvnStatusClientI client = item.getClient(ioFile); + final SvnStatusClientI client = item.getClient(); client.doStatus(ioFile, SVNRevision.WORKING, item.getDepth(), false, false, true, true, myHandler, null); myHandler.checkIfCopyRootWasReported(null, ioFile); } @@ -84,7 +84,7 @@ public class SvnRecursiveStatusWalker { } } else { try { - final SVNStatus status = item.getClient(ioFile).doStatus(ioFile, false, false); + final SVNStatus status = item.getClient().doStatus(ioFile, false, false); myReceiver.process(path, status); } catch (SVNException e) { handleStatusException(item, path, e); @@ -141,10 +141,10 @@ public class SvnRecursiveStatusWalker { return myDepth; } - public SvnStatusClientI getClient(final File file) { + public SvnStatusClientI getClient() { // TODO: refactor to ClientFactory usage but carefully save all parameters passed in myClient - fileProvider and // TODO: event handler (for cancel support) - WorkingCopyFormat format = myVcs.getWorkingCopyFormat(file); + WorkingCopyFormat format = myVcs.getWorkingCopyFormat(myPath.getIOFile()); if (format == WorkingCopyFormat.ONE_DOT_EIGHT) { return myCommandLineClient; @@ -235,7 +235,7 @@ public class SvnRecursiveStatusWalker { SVNStatus statusInner; try { statusInner = ioFileStatus != null ? ioFileStatus : - myCurrentItem.getClient(itemFile).doStatus(itemFile, false); + myCurrentItem.getClient().doStatus(itemFile, false); } catch (SVNException e) { LOG.info(e); From 93ddbc274ec51910b45a236d67ce9e78daace5ac Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 23 Apr 2014 21:02:51 +0400 Subject: [PATCH 26/65] svn: Refactored SvnChangeProvider - use common client factory model (instead of direct SVNStatusClient usage) --- .../jetbrains/idea/svn/SvnChangeProvider.java | 9 +-- .../idea/svn/SvnChangeProviderContext.java | 67 +++++++++++-------- 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java index 4c0eb5cd96b1..492be4325879 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java @@ -94,12 +94,6 @@ public class SvnChangeProvider implements ChangeProvider { walker.go(item.getDir(), SVNDepth.IMMEDIATES); } - // they are taken under non recursive: ENTRIES file is read anyway, so we get to know parent status also for free - /*for (FilePath path : zipper.getSingleFiles()) { - FileStatus status = getParentStatus(context, path); - processFile(path, context, status, false, context.getClient()); - }*/ - processCopiedAndDeleted(context, dirtyScope); processUnsaved(dirtyScope, addGate, context); @@ -251,9 +245,10 @@ public class SvnChangeProvider implements ChangeProvider { File wcPath = guessWorkingCopyPath(copiedStatus.getFile(), copiedStatus.getURL(), copyFromURL); SVNStatus status; try { - status = context.getClient().doStatus(wcPath, false); + status = myVcs.getFactory(wcPath).createStatusClient().doStatus(wcPath, false); } catch(SVNException ex) { + LOG.info(ex); status = null; } if (status != null && SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_DELETED)) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java index d99331dc4eeb..f7e5857569ff 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProviderContext.java @@ -26,9 +26,13 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.actions.AbstractShowPropertiesDiffAction; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.internal.wc17.db.ISVNWCDb; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNLock; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.wc.SVNInfo; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNStatus; +import org.tmatesoft.svn.core.wc.SVNStatusType; import java.io.File; import java.util.*; @@ -37,7 +41,6 @@ class SvnChangeProviderContext implements StatusReceiver { private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.SvnChangeProviderContext"); private final ChangelistBuilder myChangelistBuilder; - private final SVNStatusClient myStatusClient; private List myCopiedFiles = null; private final List myDeletedFiles = new ArrayList(); // for files moved in a subtree, which were the targets of merge (for instance). @@ -50,7 +53,6 @@ class SvnChangeProviderContext implements StatusReceiver { public SvnChangeProviderContext(SvnVcs vcs, final ChangelistBuilder changelistBuilder, final ProgressIndicator progress) { myVcs = vcs; - myStatusClient = vcs.createStatusClient(); myChangelistBuilder = changelistBuilder; myProgress = progress; myTreeConflicted = new HashMap(); @@ -81,10 +83,6 @@ class SvnChangeProviderContext implements StatusReceiver { return myChangelistBuilder; } - public SVNStatusClient getClient() { - return myStatusClient; - } - public void reportTreeConflict(final SVNStatus status) { myTreeConflicted.put(status.getFile().getAbsolutePath(), status); } @@ -131,7 +129,7 @@ class SvnChangeProviderContext implements StatusReceiver { return null; } StringBuilder relPathBuilder = new StringBuilder(); - while(filePath != null) { + while (filePath != null) { String copyFromURL = myCopyFromURLs.get(filePath); if (copyFromURL != null) { return copyFromURL + relPathBuilder.toString(); @@ -160,7 +158,7 @@ class SvnChangeProviderContext implements StatusReceiver { myCopyFromURLs.put(filePath, url); } -// + // void processStatusFirstPass(final FilePath filePath, final SVNStatus status) throws SVNException { if (status == null) { @@ -170,12 +168,14 @@ class SvnChangeProviderContext implements StatusReceiver { if (status.getRemoteLock() != null) { final SVNLock lock = status.getRemoteLock(); myChangelistBuilder.processLogicallyLockedFolder(filePath.getVirtualFile(), - new LogicalLock(false, lock.getOwner(), lock.getComment(), lock.getCreationDate(), lock.getExpirationDate())); + new LogicalLock(false, lock.getOwner(), lock.getComment(), lock.getCreationDate(), + lock.getExpirationDate())); } if (status.getLocalLock() != null) { final SVNLock lock = status.getLocalLock(); myChangelistBuilder.processLogicallyLockedFolder(filePath.getVirtualFile(), - new LogicalLock(true, lock.getOwner(), lock.getComment(), lock.getCreationDate(), lock.getExpirationDate())); + new LogicalLock(true, lock.getOwner(), lock.getComment(), lock.getCreationDate(), + lock.getExpirationDate())); } if (filePath.isDirectory() && status.isLocked()) { myChangelistBuilder.processLockedFolder(filePath.getVirtualFile()); @@ -191,7 +191,8 @@ class SvnChangeProviderContext implements StatusReceiver { String parentCopyFromURL = getParentCopyFromURL(filePath); if (parentCopyFromURL != null) { addCopiedFile(filePath, status, parentCopyFromURL); - } else { + } + else { processStatus(filePath, status); } } @@ -225,7 +226,8 @@ class SvnChangeProviderContext implements StatusReceiver { propStatus == SVNStatusType.STATUS_CONFLICTED) { myChangelistBuilder.processChangeInList( createChange(SvnContentRevision.createBaseRevision(myVcs, filePath, status), CurrentContentRevision.create(filePath), fStatus, - status), SvnUtil.getChangelistName(status), SvnVcs.getKey()); + status), SvnUtil.getChangelistName(status), SvnVcs.getKey() + ); checkSwitched(filePath, myChangelistBuilder, status, fStatus); } else if (SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_DELETED)) { @@ -249,16 +251,19 @@ class SvnChangeProviderContext implements StatusReceiver { if (file != null && FileDocumentManager.getInstance().isFileModified(file)) { myChangelistBuilder.processChangeInList( createChange(SvnContentRevision.createBaseRevision(myVcs, filePath, status), CurrentContentRevision.create(filePath), - FileStatus.MODIFIED, status), SvnUtil.getChangelistName(status), SvnVcs.getKey()); - } else if (status.getTreeConflict() != null) { + FileStatus.MODIFIED, status), SvnUtil.getChangelistName(status), SvnVcs.getKey() + ); + } + else if (status.getTreeConflict() != null) { myChangelistBuilder.processChange(createChange(SvnContentRevision.createBaseRevision(myVcs, filePath, status), - CurrentContentRevision.create(filePath), FileStatus.MODIFIED, status), SvnVcs.getKey()); + CurrentContentRevision.create(filePath), FileStatus.MODIFIED, status), + SvnVcs.getKey()); } checkSwitched(filePath, myChangelistBuilder, status, fStatus); } } } - + public void addModifiedNotSavedChange(final VirtualFile file) throws SVNException { final FilePath filePath = new FilePathImpl(file); final SVNInfo svnInfo = myVcs.getInfo(file); @@ -268,7 +273,8 @@ class SvnChangeProviderContext implements StatusReceiver { svnStatus.setRevision(svnInfo.getRevision()); myChangelistBuilder.processChangeInList( createChange(SvnContentRevision.createBaseRevision(myVcs, filePath, svnInfo.getRevision()), CurrentContentRevision.create(filePath), - FileStatus.MODIFIED, svnStatus), (String)null, SvnVcs.getKey()); + FileStatus.MODIFIED, svnStatus), (String)null, SvnVcs.getKey() + ); } } @@ -317,7 +323,7 @@ class SvnChangeProviderContext implements StatusReceiver { // seems here we can only have a tree conflict; which can be marked on either path (?) // .. ok try to merge states Change createMovedChange(final ContentRevision before, final ContentRevision after, final SVNStatus copiedStatus, - final SVNStatus deletedStatus) throws SVNException { + final SVNStatus deletedStatus) throws SVNException { // todo no convertion needed for the contents status? final ConflictedSvnChange conflictedSvnChange = new ConflictedSvnChange(before, after, ConflictState.mergeState(getState(copiedStatus), getState(deletedStatus)), @@ -331,12 +337,16 @@ class SvnChangeProviderContext implements StatusReceiver { return patchWithPropertyChange(conflictedSvnChange, copiedStatus, deletedStatus); } - private Change createChange(final ContentRevision before, final ContentRevision after, final FileStatus fStatus, final SVNStatus svnStatus) + private Change createChange(final ContentRevision before, + final ContentRevision after, + final FileStatus fStatus, + final SVNStatus svnStatus) throws SVNException { final ConflictedSvnChange conflictedSvnChange = new ConflictedSvnChange(before, after, correctContentsStatus(fStatus, svnStatus), - getState(svnStatus), after == null ? before.getFile() : after.getFile()); + getState(svnStatus), + after == null ? before.getFile() : after.getFile()); if (svnStatus != null) { - if (SVNStatusType.STATUS_DELETED.equals(svnStatus.getNodeStatus()) && ! svnStatus.getRevision().isValid()) { + if (SVNStatusType.STATUS_DELETED.equals(svnStatus.getNodeStatus()) && !svnStatus.getRevision().isValid()) { conflictedSvnChange.setIsPhantom(true); } conflictedSvnChange.setBeforeDescription(svnStatus.getTreeConflict()); @@ -354,7 +364,8 @@ class SvnChangeProviderContext implements StatusReceiver { return new SvnLocallyDeletedChange(filePath, getState(status)); } - private Change patchWithPropertyChange(final Change change, final SVNStatus svnStatus, final SVNStatus deletedStatus) throws SVNException { + private Change patchWithPropertyChange(final Change change, final SVNStatus svnStatus, final SVNStatus deletedStatus) + throws SVNException { if (svnStatus == null) return change; final SVNStatusType propertiesStatus = svnStatus.getPropertiesStatus(); if (SVNStatusType.STATUS_CONFLICTED.equals(propertiesStatus) || SVNStatusType.CHANGED.equals(propertiesStatus) || @@ -378,8 +389,10 @@ class SvnChangeProviderContext implements StatusReceiver { final String afterRevisionNu = change.getAfterRevision() == null ? null : change.getAfterRevision().getRevisionNumber().asString(); final Change propertyChange = new Change(beforeList == null ? null : new SimpleContentRevision(beforeList, path, beforeRevisionNu), - afterList == null ? null : new SimpleContentRevision(afterList, path, afterRevisionNu), - deletedStatus != null ? FileStatus.MODIFIED : SvnStatusConvertor.convertPropertyStatus(propertiesStatus)); + afterList == null ? null : new SimpleContentRevision(afterList, path, afterRevisionNu), + deletedStatus != null + ? FileStatus.MODIFIED + : SvnStatusConvertor.convertPropertyStatus(propertiesStatus)); change.addAdditionalLayerElement(SvnChangeProvider.PROPERTY_LAYER, propertyChange); } return change; From 3ca64b6c24d73cc38e12487d7dbdd8dda8003d58 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 23 Apr 2014 21:13:30 +0400 Subject: [PATCH 27/65] svn: Merged StatusWalkerPartner interface and StatusWalkerPartnerImpl implementation to single class --- .../idea/svn/StatusWalkerPartner.java | 71 +++++++++++++-- .../idea/svn/StatusWalkerPartnerImpl.java | 87 ------------------- .../jetbrains/idea/svn/SvnChangeProvider.java | 4 +- 3 files changed, 68 insertions(+), 94 deletions(-) delete mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartnerImpl.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java index adba27a55143..296b4e9d38f0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java @@ -15,12 +15,73 @@ */ package org.jetbrains.idea.svn; +import com.intellij.lifecycle.PeriodicalTasksCloser; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.roots.FileIndexFacade; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vfs.VirtualFile; +import org.tmatesoft.svn.core.SVNCancelException; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.wc.ISVNEventHandler; +import org.tmatesoft.svn.core.wc.ISVNStatusFileProvider; +import org.tmatesoft.svn.core.wc.SVNEvent; import org.tmatesoft.svn.core.wc.SVNStatusClient; -public interface StatusWalkerPartner { - SVNStatusClient createStatusClient(); - void checkCanceled(); - boolean isExcluded(final VirtualFile vFile); - boolean isIgnoredIdeaLevel(final VirtualFile vFile); +public class StatusWalkerPartner { + private final SvnVcs myVcs; + private final ChangeListManager myClManager; + private final FileIndexFacade myExcludedFileIndex; + private final ProgressIndicator myIndicator; + private ISVNStatusFileProvider myFileProvider; + + public StatusWalkerPartner(final SvnVcs vcs, final ProgressIndicator pi) { + myVcs = vcs; + myClManager = ChangeListManager.getInstance(myVcs.getProject()); + myExcludedFileIndex = PeriodicalTasksCloser.getInstance().safeGetService(myVcs.getProject(), FileIndexFacade.class); + myIndicator = pi; + } + + public void setFileProvider(final ISVNStatusFileProvider fileProvider) { + myFileProvider = fileProvider; + } + + public SVNStatusClient createStatusClient() { + final SVNStatusClient result = myVcs.createStatusClient(); + result.setFilesProvider(myFileProvider); + result.setEventHandler(new ISVNEventHandler() { + public void handleEvent(SVNEvent event, double progress) throws SVNException { + // + } + + public void checkCancelled() throws SVNCancelException { + if (myIndicator != null) { + myIndicator.checkCanceled(); + } + } + }); + return result; + } + + public void checkCanceled() { + if (myIndicator != null) { + myIndicator.checkCanceled(); + } + } + + public boolean isExcluded(final VirtualFile vFile) { + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Boolean compute() { + if (myVcs.getProject().isDisposed()) throw new ProcessCanceledException(); + return myExcludedFileIndex.isExcludedFile(vFile); + } + }); + } + + public boolean isIgnoredIdeaLevel(VirtualFile vFile) { + return myClManager.isIgnoredFile(vFile); + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartnerImpl.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartnerImpl.java deleted file mode 100644 index 15bc2b866c3e..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartnerImpl.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.svn; - -import com.intellij.lifecycle.PeriodicalTasksCloser; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.roots.FileIndexFacade; -import com.intellij.openapi.util.Computable; -import com.intellij.openapi.vcs.changes.ChangeListManager; -import com.intellij.openapi.vfs.VirtualFile; -import org.tmatesoft.svn.core.SVNCancelException; -import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.wc.ISVNEventHandler; -import org.tmatesoft.svn.core.wc.ISVNStatusFileProvider; -import org.tmatesoft.svn.core.wc.SVNEvent; -import org.tmatesoft.svn.core.wc.SVNStatusClient; - -public class StatusWalkerPartnerImpl implements StatusWalkerPartner { - private final SvnVcs myVcs; - private final ChangeListManager myClManager; - private final FileIndexFacade myExcludedFileIndex; - private final ProgressIndicator myIndicator; - private ISVNStatusFileProvider myFileProvider; - - public StatusWalkerPartnerImpl(final SvnVcs vcs, final ProgressIndicator pi) { - myVcs = vcs; - myClManager = ChangeListManager.getInstance(myVcs.getProject()); - myExcludedFileIndex = PeriodicalTasksCloser.getInstance().safeGetService(myVcs.getProject(), FileIndexFacade.class); - myIndicator = pi; - } - - public void setFileProvider(final ISVNStatusFileProvider fileProvider) { - myFileProvider = fileProvider; - } - - public SVNStatusClient createStatusClient() { - final SVNStatusClient result = myVcs.createStatusClient(); - result.setFilesProvider(myFileProvider); - result.setEventHandler(new ISVNEventHandler() { - public void handleEvent(SVNEvent event, double progress) throws SVNException { - // - } - - public void checkCancelled() throws SVNCancelException { - if (myIndicator != null) { - myIndicator.checkCanceled(); - } - } - }); - return result; - } - - public void checkCanceled() { - if (myIndicator != null) { - myIndicator.checkCanceled(); - } - } - - public boolean isExcluded(final VirtualFile vFile) { - return ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public Boolean compute() { - if (myVcs.getProject().isDisposed()) throw new ProcessCanceledException(); - return myExcludedFileIndex.isExcludedFile(vFile); - } - }); - } - - public boolean isIgnoredIdeaLevel(VirtualFile vFile) { - return myClManager.isIgnoredFile(vFile); - } -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java index 492be4325879..85bc9b1a7f02 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java @@ -76,7 +76,7 @@ public class SvnChangeProvider implements ChangeProvider { try { final SvnChangeProviderContext context = new SvnChangeProviderContext(myVcs, builder, progress); - final StatusWalkerPartnerImpl partner = new StatusWalkerPartnerImpl(myVcs, progress); + final StatusWalkerPartner partner = new StatusWalkerPartner(myVcs, progress); final NestedCopiesBuilder nestedCopiesBuilder = new NestedCopiesBuilder(myVcs, mySvnFileUrlMapping); final EventDispatcher statusReceiver = EventDispatcher.create(StatusReceiver.class); @@ -171,7 +171,7 @@ public class SvnChangeProvider implements ChangeProvider { public void getChanges(final FilePath path, final boolean recursive, final ChangelistBuilder builder) throws SVNException { final SvnChangeProviderContext context = new SvnChangeProviderContext(myVcs, builder, null); - final StatusWalkerPartnerImpl partner = new StatusWalkerPartnerImpl(myVcs, ProgressManager.getInstance().getProgressIndicator()); + final StatusWalkerPartner partner = new StatusWalkerPartner(myVcs, ProgressManager.getInstance().getProgressIndicator()); final SvnRecursiveStatusWalker walker = new SvnRecursiveStatusWalker(myVcs, context, partner); walker.go(path, recursive ? SVNDepth.INFINITY : SVNDepth.IMMEDIATES); processCopiedAndDeleted(context, null); From 343ea1cc0143c62aa92bd97d50aac7dbeb6e8b51 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 23 Apr 2014 21:18:51 +0400 Subject: [PATCH 28/65] svn: Refactored SvnRecursiveStatusWalker - methods extracted, warnings fixes --- .../idea/svn/SvnRecursiveStatusWalker.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java index b311921a81ec..021681a935d2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java @@ -62,7 +62,7 @@ public class SvnRecursiveStatusWalker { } public void go(final FilePath rootPath, final SVNDepth depth) throws SVNException { - final MyItem root = new MyItem(myVcs, rootPath, depth, myPartner.createStatusClient(), false); + final MyItem root = createItem(rootPath, depth, false); myQueue.add(root); while (! myQueue.isEmpty()) { @@ -187,7 +187,7 @@ public class SvnRecursiveStatusWalker { return true; } if (file.isDirectory() && new File(file, SVNFileUtil.getAdminDirectoryName()).exists()) { - final MyItem childItem = new MyItem(myVcs, path, newDepth, myPartner.createStatusClient(), true); + final MyItem childItem = createItem(path, newDepth, true); myQueue.add(childItem); } else if (vf != null) { myReceiver.processUnversioned(vf); @@ -219,6 +219,10 @@ public class SvnRecursiveStatusWalker { FileUtil.processFilesRecursively(ioFile, processor, directoryFilter); } + private MyItem createItem(FilePath path, SVNDepth depth, boolean isInnerCopyRoot) { + return new MyItem(myVcs, path, depth, myPartner.createStatusClient(), isInnerCopyRoot); + } + private class MyHandler implements ISVNStatusHandler { private MyItem myCurrentItem; private boolean myMetCurrentItem; @@ -295,8 +299,7 @@ public class SvnRecursiveStatusWalker { //myReceiver.processUnversioned(vFile); //processRecursively(vFile, myCurrentItem.getDepth()); } else { - final MyItem childItem = new MyItem(myVcs, new FilePathImpl(vFile), SVNDepth.INFINITY, - myPartner.createStatusClient(), true); + final MyItem childItem = createItem(new FilePathImpl(vFile), SVNDepth.INFINITY, true); myQueue.add(childItem); } } else { @@ -309,7 +312,7 @@ public class SvnRecursiveStatusWalker { } } - private VirtualFile getVirtualFile(File ioFile) { + private static VirtualFile getVirtualFile(File ioFile) { final LocalFileSystem lfs = LocalFileSystem.getInstance(); VirtualFile vFile = lfs.findFileByIoFile(ioFile); if (vFile == null) { From 1d31c6822533dcea9a1a850d21a57cb613bb246b Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 23 Apr 2014 22:32:05 +0400 Subject: [PATCH 29/65] svn: Refactored SvnRecursiveStatusWalker.MyItem - use common client factory model (instead of direct SVNStatusClient usage) --- .../idea/svn/StatusWalkerPartner.java | 18 ++++--- .../idea/svn/SvnRecursiveStatusWalker.java | 51 ++++++++----------- .../jetbrains/idea/svn/api/ClientFactory.java | 8 +++ .../idea/svn/api/SvnKitClientFactory.java | 12 ++++- .../svn/portable/SvnkitSvnStatusClient.java | 32 +++++++++--- 5 files changed, 74 insertions(+), 47 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java index 296b4e9d38f0..09d7d87ec1dc 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/StatusWalkerPartner.java @@ -23,12 +23,13 @@ import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.ISVNStatusFileProvider; import org.tmatesoft.svn.core.wc.SVNEvent; -import org.tmatesoft.svn.core.wc.SVNStatusClient; public class StatusWalkerPartner { private final SvnVcs myVcs; @@ -48,10 +49,9 @@ public class StatusWalkerPartner { myFileProvider = fileProvider; } - public SVNStatusClient createStatusClient() { - final SVNStatusClient result = myVcs.createStatusClient(); - result.setFilesProvider(myFileProvider); - result.setEventHandler(new ISVNEventHandler() { + @NotNull + public ISVNEventHandler getEventHandler() { + return new ISVNEventHandler() { public void handleEvent(SVNEvent event, double progress) throws SVNException { // } @@ -61,8 +61,12 @@ public class StatusWalkerPartner { myIndicator.checkCanceled(); } } - }); - return result; + }; + } + + @Nullable + public ISVNStatusFileProvider getFileProvider() { + return myFileProvider; } public void checkCanceled() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java index 021681a935d2..6d4dba48192b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java @@ -29,16 +29,18 @@ import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Processor; import com.intellij.vcsUtil.VcsUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient; import org.jetbrains.idea.svn.portable.SvnStatusClientI; -import org.jetbrains.idea.svn.portable.SvnkitSvnStatusClient; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.ISVNStatusHandler; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNStatus; +import org.tmatesoft.svn.core.wc.SVNStatusType; import java.io.File; import java.util.LinkedList; @@ -113,48 +115,31 @@ public class SvnRecursiveStatusWalker { } private static class MyItem { - private final Project myProject; - private final FilePath myPath; - private final SVNDepth myDepth; - private final SvnStatusClientI mySvnClient; - private final SvnStatusClientI myCommandLineClient; + @NotNull private final FilePath myPath; + @NotNull private final SVNDepth myDepth; + @NotNull private final SvnStatusClientI myStatusClient; private final boolean myIsInnerCopyRoot; - private final SvnConfiguration myConfiguration17; - private final SvnVcs myVcs; - private MyItem(SvnVcs vcs, FilePath path, SVNDepth depth, SVNStatusClient client, boolean isInnerCopyRoot) { - myVcs = vcs; - myProject = vcs.getProject(); - myConfiguration17 = SvnConfiguration.getInstance(myProject); + private MyItem(@NotNull FilePath path, @NotNull SVNDepth depth, boolean isInnerCopyRoot, @NotNull SvnStatusClientI statusClient) { myPath = path; myDepth = depth; - mySvnClient = new SvnkitSvnStatusClient(myVcs, client); - myCommandLineClient = new SvnCommandLineStatusClient(myVcs); + myStatusClient = statusClient; myIsInnerCopyRoot = isInnerCopyRoot; } + @NotNull public FilePath getPath() { return myPath; } + @NotNull public SVNDepth getDepth() { return myDepth; } + @NotNull public SvnStatusClientI getClient() { - // TODO: refactor to ClientFactory usage but carefully save all parameters passed in myClient - fileProvider and - // TODO: event handler (for cancel support) - WorkingCopyFormat format = myVcs.getWorkingCopyFormat(myPath.getIOFile()); - - if (format == WorkingCopyFormat.ONE_DOT_EIGHT) { - return myCommandLineClient; - } - - if (format == WorkingCopyFormat.ONE_DOT_SIX) { - return mySvnClient; - } - - return myConfiguration17.isCommandLine() ? myCommandLineClient : mySvnClient; + return myStatusClient; } public boolean isIsInnerCopyRoot() { @@ -219,8 +204,12 @@ public class SvnRecursiveStatusWalker { FileUtil.processFilesRecursively(ioFile, processor, directoryFilter); } - private MyItem createItem(FilePath path, SVNDepth depth, boolean isInnerCopyRoot) { - return new MyItem(myVcs, path, depth, myPartner.createStatusClient(), isInnerCopyRoot); + @NotNull + private MyItem createItem(@NotNull FilePath path, @NotNull SVNDepth depth, boolean isInnerCopyRoot) { + SvnStatusClientI statusClient = + myVcs.getFactory(path.getIOFile()).createStatusClient(myPartner.getFileProvider(), myPartner.getEventHandler()); + + return new MyItem(path, depth, isInnerCopyRoot, statusClient); } private class MyHandler implements ISVNStatusHandler { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java index 441399fab0a4..c90eeb03e07a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java @@ -1,6 +1,7 @@ package org.jetbrains.idea.svn.api; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.add.AddClient; import org.jetbrains.idea.svn.annotate.AnnotateClient; @@ -26,6 +27,8 @@ import org.jetbrains.idea.svn.revert.RevertClient; import org.jetbrains.idea.svn.update.RelocateClient; import org.jetbrains.idea.svn.update.UpdateClient; import org.jetbrains.idea.svn.upgrade.UpgradeClient; +import org.tmatesoft.svn.core.wc.ISVNEventHandler; +import org.tmatesoft.svn.core.wc.ISVNStatusFileProvider; /** * @author Konstantin Kolosovsky. @@ -98,6 +101,11 @@ public abstract class ClientFactory { return statusClient; } + @NotNull + public SvnStatusClientI createStatusClient(@Nullable ISVNStatusFileProvider provider, @NotNull ISVNEventHandler handler) { + return createStatusClient(); + } + @NotNull public SvnWcClientI createInfoClient() { // TODO: Update this in same like other clients - move to corresponding package, rename clients diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java index 95cfe0c224f7..0fb3655e1989 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java @@ -1,6 +1,7 @@ package org.jetbrains.idea.svn.api; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.add.SvnKitAddClient; import org.jetbrains.idea.svn.annotate.SvnKitAnnotateClient; @@ -19,6 +20,7 @@ import org.jetbrains.idea.svn.diff.SvnKitDiffClient; import org.jetbrains.idea.svn.history.SvnKitHistoryClient; import org.jetbrains.idea.svn.integrate.SvnKitMergeClient; import org.jetbrains.idea.svn.lock.SvnKitLockClient; +import org.jetbrains.idea.svn.portable.SvnStatusClientI; import org.jetbrains.idea.svn.portable.SvnkitSvnStatusClient; import org.jetbrains.idea.svn.portable.SvnkitSvnWcClient; import org.jetbrains.idea.svn.properties.SvnKitPropertyClient; @@ -27,6 +29,8 @@ import org.jetbrains.idea.svn.update.SvnKitRelocateClient; import org.jetbrains.idea.svn.update.SvnKitUpdateClient; import org.jetbrains.idea.svn.update.UpdateClient; import org.jetbrains.idea.svn.upgrade.SvnKitUpgradeClient; +import org.tmatesoft.svn.core.wc.ISVNEventHandler; +import org.tmatesoft.svn.core.wc.ISVNStatusFileProvider; /** * @author Konstantin Kolosovsky. @@ -61,10 +65,16 @@ public class SvnKitClientFactory extends ClientFactory { myBrowseClient = new SvnKitBrowseClient(); myDiffClient = new SvnKitDiffClient(); myCheckinClient = new SvnKitCheckinClient(); - statusClient = new SvnkitSvnStatusClient(myVcs, null); + statusClient = new SvnkitSvnStatusClient(myVcs); infoClient = new SvnkitSvnWcClient(myVcs); } + @NotNull + @Override + public SvnStatusClientI createStatusClient(@Nullable ISVNStatusFileProvider provider, @NotNull ISVNEventHandler handler) { + return new SvnkitSvnStatusClient(myVcs, provider, handler); + } + @NotNull @Override public UpdateClient createUpdateClient() { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnStatusClient.java index 07edfa25fa61..03a8d7deaf2e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnStatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnStatusClient.java @@ -20,10 +20,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.wc.ISVNStatusHandler; -import org.tmatesoft.svn.core.wc.SVNRevision; -import org.tmatesoft.svn.core.wc.SVNStatus; -import org.tmatesoft.svn.core.wc.SVNStatusClient; +import org.tmatesoft.svn.core.wc.*; import java.io.File; import java.util.Collection; @@ -36,12 +33,19 @@ import java.util.Collection; */ public class SvnkitSvnStatusClient implements SvnStatusClientI { - @Nullable private final SVNStatusClient myStatusClient; + private SVNStatusClient myStatusClient; @NotNull private final SvnVcs myVcs; + @Nullable private final ISVNStatusFileProvider myProvider; + @Nullable private final ISVNEventHandler myHandler; - public SvnkitSvnStatusClient(@NotNull SvnVcs vcs, @Nullable SVNStatusClient statusClient) { + public SvnkitSvnStatusClient(@NotNull SvnVcs vcs) { + this(vcs, null, null); + } + + public SvnkitSvnStatusClient(@NotNull SvnVcs vcs, @Nullable ISVNStatusFileProvider provider, @Nullable ISVNEventHandler handler) { myVcs = vcs; - myStatusClient = statusClient; + myProvider = provider; + myHandler = handler; } @Override @@ -99,6 +103,18 @@ public class SvnkitSvnStatusClient implements SvnStatusClientI { @NotNull private SVNStatusClient getStatusClient() { - return myStatusClient != null ? myStatusClient : myVcs.createStatusClient(); + // if either provider or handler is specified - we reuse same status client for all further doStatus() calls + return myHandler != null || myProvider != null ? ensureStatusClient() : myVcs.createStatusClient(); + } + + @NotNull + private SVNStatusClient ensureStatusClient() { + if (myStatusClient == null) { + myStatusClient = myVcs.createStatusClient(); + myStatusClient.setFilesProvider(myProvider); + myStatusClient.setEventHandler(myHandler); + } + + return myStatusClient; } } From 39d7edd695a4c0a1f69ca64129416dd40ff45eff Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 23 Apr 2014 22:45:55 +0400 Subject: [PATCH 30/65] svn: Make status clients (both for SVNKit and command line) satisfy common client factory model --- .../jetbrains/idea/svn/api/ClientFactory.java | 3 +-- .../jetbrains/idea/svn/api/CmdClientFactory.java | 4 ++-- .../idea/svn/api/SvnKitClientFactory.java | 4 ++-- .../idea/svn/checkin/CmdCheckinClient.java | 3 ++- .../commandLine/SvnCommandLineStatusClient.java | 16 ++++------------ .../idea/svn/portable/SvnStatusClientI.java | 3 ++- .../idea/svn/portable/SvnkitSvnStatusClient.java | 12 +++++------- 7 files changed, 18 insertions(+), 27 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java index c90eeb03e07a..9620a55af701 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java @@ -97,8 +97,7 @@ public abstract class ClientFactory { @NotNull public SvnStatusClientI createStatusClient() { - // TODO: Update this in same like other clients - move to corresponding package, rename clients - return statusClient; + return prepare(statusClient); } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java index 601b3d170600..76164bb13516 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java @@ -6,13 +6,13 @@ import org.jetbrains.idea.svn.add.CmdAddClient; import org.jetbrains.idea.svn.annotate.CmdAnnotateClient; import org.jetbrains.idea.svn.browse.CmdBrowseClient; import org.jetbrains.idea.svn.change.CmdChangeListClient; +import org.jetbrains.idea.svn.checkin.CmdCheckinClient; import org.jetbrains.idea.svn.checkin.CmdImportClient; import org.jetbrains.idea.svn.checkout.CmdCheckoutClient; import org.jetbrains.idea.svn.checkout.CmdExportClient; import org.jetbrains.idea.svn.cleanup.CmdCleanupClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient; -import org.jetbrains.idea.svn.checkin.CmdCheckinClient; import org.jetbrains.idea.svn.conflict.CmdConflictClient; import org.jetbrains.idea.svn.content.CmdContentClient; import org.jetbrains.idea.svn.copy.CmdCopyMoveClient; @@ -61,7 +61,7 @@ public class CmdClientFactory extends ClientFactory { myBrowseClient = new CmdBrowseClient(); myDiffClient = new CmdDiffClient(); myCheckinClient = new CmdCheckinClient(); - statusClient = new SvnCommandLineStatusClient(myVcs); + statusClient = new SvnCommandLineStatusClient(); infoClient = new SvnCommandLineInfoClient(myVcs); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java index 0fb3655e1989..8767f092e25f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java @@ -65,14 +65,14 @@ public class SvnKitClientFactory extends ClientFactory { myBrowseClient = new SvnKitBrowseClient(); myDiffClient = new SvnKitDiffClient(); myCheckinClient = new SvnKitCheckinClient(); - statusClient = new SvnkitSvnStatusClient(myVcs); + statusClient = new SvnkitSvnStatusClient(); infoClient = new SvnkitSvnWcClient(myVcs); } @NotNull @Override public SvnStatusClientI createStatusClient(@Nullable ISVNStatusFileProvider provider, @NotNull ISVNEventHandler handler) { - return new SvnkitSvnStatusClient(myVcs, provider, handler); + return prepare(new SvnkitSvnStatusClient(provider, handler)); } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java index 0e43b4afcde6..7a344c8c171e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java @@ -29,6 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.commandLine.*; +import org.jetbrains.idea.svn.portable.SvnStatusClientI; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; @@ -125,7 +126,7 @@ public class CmdCheckinClient extends BaseSvnClient implements CheckinClient { }.doFilter(ContainerUtil.newArrayList(committables)); if (!childrenOfSomebody.isEmpty()) { List result = ContainerUtil.newArrayList(); - SvnCommandLineStatusClient statusClient = new SvnCommandLineStatusClient(myVcs); + SvnStatusClientI statusClient = myFactory.createStatusClient(); for (File file : committables) { if (!childrenOfSomebody.contains(file.getPath())) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java index 236aeadc80dc..1b31d152f07e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java @@ -25,7 +25,7 @@ import com.intellij.util.containers.Convertor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnUtil; -import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.portable.PortableStatus; import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; import org.jetbrains.idea.svn.portable.SvnStatusClientI; @@ -49,17 +49,9 @@ import java.util.*; * Date: 1/25/12 * Time: 5:21 PM */ -public class SvnCommandLineStatusClient implements SvnStatusClientI { +public class SvnCommandLineStatusClient extends BaseSvnClient implements SvnStatusClientI { private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient"); - private final SvnCommandLineInfoClient myInfoClient; - @NotNull private final SvnVcs myVcs; - - public SvnCommandLineStatusClient(@NotNull SvnVcs vcs) { - myVcs = vcs; - myInfoClient = new SvnCommandLineInfoClient(vcs); - } - @Override public long doStatus(File path, boolean recursive, boolean remote, boolean reportAll, boolean includeIgnored, ISVNStatusHandler handler) throws SVNException { @@ -103,7 +95,7 @@ public class SvnCommandLineStatusClient implements SvnStatusClientI { File base = path.isDirectory() ? path : path.getParentFile(); base = CommandUtil.correctUpToExistingParent(base); - final SVNInfo infoBase = myInfoClient.doInfo(base, revision); + final SVNInfo infoBase = myFactory.createInfoClient().doInfo(base, revision); List parameters = new ArrayList(); putParameters(parameters, path, depth, remote, reportAll, includeIgnored, changeLists); @@ -211,7 +203,7 @@ public class SvnCommandLineStatusClient implements SvnStatusClientI { @Override public SVNInfo convert(File o) { try { - return myInfoClient.doInfo(o, revision); + return myFactory.createInfoClient().doInfo(o, revision); } catch (SVNException e) { throw new SvnExceptionWrapper(e); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnStatusClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnStatusClientI.java index 3b5828239abd..b7394da8d117 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnStatusClientI.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnStatusClientI.java @@ -15,6 +15,7 @@ */ package org.jetbrains.idea.svn.portable; +import org.jetbrains.idea.svn.api.SvnClient; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.ISVNStatusHandler; @@ -30,7 +31,7 @@ import java.util.Collection; * Date: 1/24/12 * Time: 9:46 AM */ -public interface SvnStatusClientI extends SvnMarkerInterface { +public interface SvnStatusClientI extends SvnClient { long doStatus(File path, boolean recursive, boolean remote, boolean reportAll, boolean includeIgnored, ISVNStatusHandler handler) throws SVNException; long doStatus(File path, boolean recursive, boolean remote, boolean reportAll, boolean includeIgnored, boolean collectParentExternals, ISVNStatusHandler handler) throws SVNException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnStatusClient.java index 03a8d7deaf2e..a59283ab1091 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnStatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnStatusClient.java @@ -17,7 +17,7 @@ package org.jetbrains.idea.svn.portable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.api.BaseSvnClient; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.*; @@ -31,19 +31,17 @@ import java.util.Collection; * Date: 1/24/12 * Time: 9:47 AM */ -public class SvnkitSvnStatusClient implements SvnStatusClientI { +public class SvnkitSvnStatusClient extends BaseSvnClient implements SvnStatusClientI { private SVNStatusClient myStatusClient; - @NotNull private final SvnVcs myVcs; @Nullable private final ISVNStatusFileProvider myProvider; @Nullable private final ISVNEventHandler myHandler; - public SvnkitSvnStatusClient(@NotNull SvnVcs vcs) { - this(vcs, null, null); + public SvnkitSvnStatusClient() { + this(null, null); } - public SvnkitSvnStatusClient(@NotNull SvnVcs vcs, @Nullable ISVNStatusFileProvider provider, @Nullable ISVNEventHandler handler) { - myVcs = vcs; + public SvnkitSvnStatusClient(@Nullable ISVNStatusFileProvider provider, @Nullable ISVNEventHandler handler) { myProvider = provider; myHandler = handler; } From 7b6f441e2a0c7eb389ac4adef086597dfe12bfb8 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 13:36:31 +0400 Subject: [PATCH 31/65] svn: Renamed status clients for both SVNKit and command line (interface and implementations) --- .../jetbrains/idea/svn/SvnRecursiveStatusWalker.java | 12 ++++++------ .../idea/svn/actions/MarkResolvedAction.java | 4 ++-- .../org/jetbrains/idea/svn/api/ClientFactory.java | 8 ++++---- .../org/jetbrains/idea/svn/api/CmdClientFactory.java | 4 ++-- .../jetbrains/idea/svn/api/SvnKitClientFactory.java | 10 +++++----- .../jetbrains/idea/svn/checkin/CmdCheckinClient.java | 4 ++-- ...andLineStatusClient.java => CmdStatusClient.java} | 8 +++----- .../{SvnStatusClientI.java => StatusClient.java} | 2 +- ...tSvnStatusClient.java => SvnKitStatusClient.java} | 6 +++--- .../svn/treeConflict/SvnTreeConflictResolver.java | 4 ++-- .../idea/svn/SvnParseCommandLineParseTest.java | 11 +++++++---- 11 files changed, 37 insertions(+), 36 deletions(-) rename plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/{SvnCommandLineStatusClient.java => CmdStatusClient.java} (97%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/portable/{SvnStatusClientI.java => StatusClient.java} (97%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/portable/{SvnkitSvnStatusClient.java => SvnKitStatusClient.java} (94%) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java index 6d4dba48192b..65c953ddd7e6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java @@ -31,7 +31,7 @@ import com.intellij.util.Processor; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.portable.SvnStatusClientI; +import org.jetbrains.idea.svn.portable.StatusClient; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNException; @@ -77,7 +77,7 @@ public class SvnRecursiveStatusWalker { if (path.isDirectory()) { myHandler.setCurrentItem(item); try { - final SvnStatusClientI client = item.getClient(); + final StatusClient client = item.getClient(); client.doStatus(ioFile, SVNRevision.WORKING, item.getDepth(), false, false, true, true, myHandler, null); myHandler.checkIfCopyRootWasReported(null, ioFile); } @@ -117,10 +117,10 @@ public class SvnRecursiveStatusWalker { private static class MyItem { @NotNull private final FilePath myPath; @NotNull private final SVNDepth myDepth; - @NotNull private final SvnStatusClientI myStatusClient; + @NotNull private final StatusClient myStatusClient; private final boolean myIsInnerCopyRoot; - private MyItem(@NotNull FilePath path, @NotNull SVNDepth depth, boolean isInnerCopyRoot, @NotNull SvnStatusClientI statusClient) { + private MyItem(@NotNull FilePath path, @NotNull SVNDepth depth, boolean isInnerCopyRoot, @NotNull StatusClient statusClient) { myPath = path; myDepth = depth; myStatusClient = statusClient; @@ -138,7 +138,7 @@ public class SvnRecursiveStatusWalker { } @NotNull - public SvnStatusClientI getClient() { + public StatusClient getClient() { return myStatusClient; } @@ -206,7 +206,7 @@ public class SvnRecursiveStatusWalker { @NotNull private MyItem createItem(@NotNull FilePath path, @NotNull SVNDepth depth, boolean isInnerCopyRoot) { - SvnStatusClientI statusClient = + StatusClient statusClient = myVcs.getFactory(path.getIOFile()).createStatusClient(myPartner.getFileProvider(), myPartner.getEventHandler()); return new MyItem(path, depth, isInnerCopyRoot, statusClient); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java index 21baf2d925ba..73c7c579ba55 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java @@ -35,7 +35,7 @@ import org.jetbrains.idea.svn.SvnStatusUtil; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.conflict.ConflictClient; import org.jetbrains.idea.svn.dialogs.SelectFilesDialog; -import org.jetbrains.idea.svn.portable.SvnStatusClientI; +import org.jetbrains.idea.svn.portable.StatusClient; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.*; @@ -122,7 +122,7 @@ public class MarkResolvedAction extends BasicAction { for (VirtualFile file : files) { try { File path = new File(file.getPath()); - SvnStatusClientI client = vcs.getFactory(path).createStatusClient(); + StatusClient client = vcs.getFactory(path).createStatusClient(); client.doStatus(path, true, false, false, false, new ISVNStatusHandler() { public void handleStatus(SVNStatus status) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java index 9620a55af701..7b21511a7ae5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java @@ -20,7 +20,7 @@ import org.jetbrains.idea.svn.diff.DiffClient; import org.jetbrains.idea.svn.history.HistoryClient; import org.jetbrains.idea.svn.integrate.MergeClient; import org.jetbrains.idea.svn.lock.LockClient; -import org.jetbrains.idea.svn.portable.SvnStatusClientI; +import org.jetbrains.idea.svn.portable.StatusClient; import org.jetbrains.idea.svn.portable.SvnWcClientI; import org.jetbrains.idea.svn.properties.PropertyClient; import org.jetbrains.idea.svn.revert.RevertClient; @@ -44,7 +44,7 @@ public abstract class ClientFactory { protected HistoryClient historyClient; protected RevertClient revertClient; protected DeleteClient deleteClient; - protected SvnStatusClientI statusClient; + protected StatusClient statusClient; protected SvnWcClientI infoClient; protected CopyMoveClient copyMoveClient; protected ConflictClient conflictClient; @@ -96,12 +96,12 @@ public abstract class ClientFactory { } @NotNull - public SvnStatusClientI createStatusClient() { + public StatusClient createStatusClient() { return prepare(statusClient); } @NotNull - public SvnStatusClientI createStatusClient(@Nullable ISVNStatusFileProvider provider, @NotNull ISVNEventHandler handler) { + public StatusClient createStatusClient(@Nullable ISVNStatusFileProvider provider, @NotNull ISVNEventHandler handler) { return createStatusClient(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java index 76164bb13516..84e195f3326d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java @@ -11,8 +11,8 @@ import org.jetbrains.idea.svn.checkin.CmdImportClient; import org.jetbrains.idea.svn.checkout.CmdCheckoutClient; import org.jetbrains.idea.svn.checkout.CmdExportClient; import org.jetbrains.idea.svn.cleanup.CmdCleanupClient; +import org.jetbrains.idea.svn.commandLine.CmdStatusClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient; -import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient; import org.jetbrains.idea.svn.conflict.CmdConflictClient; import org.jetbrains.idea.svn.content.CmdContentClient; import org.jetbrains.idea.svn.copy.CmdCopyMoveClient; @@ -61,7 +61,7 @@ public class CmdClientFactory extends ClientFactory { myBrowseClient = new CmdBrowseClient(); myDiffClient = new CmdDiffClient(); myCheckinClient = new CmdCheckinClient(); - statusClient = new SvnCommandLineStatusClient(); + statusClient = new CmdStatusClient(); infoClient = new SvnCommandLineInfoClient(myVcs); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java index 8767f092e25f..3183fcf11c46 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java @@ -20,8 +20,8 @@ import org.jetbrains.idea.svn.diff.SvnKitDiffClient; import org.jetbrains.idea.svn.history.SvnKitHistoryClient; import org.jetbrains.idea.svn.integrate.SvnKitMergeClient; import org.jetbrains.idea.svn.lock.SvnKitLockClient; -import org.jetbrains.idea.svn.portable.SvnStatusClientI; -import org.jetbrains.idea.svn.portable.SvnkitSvnStatusClient; +import org.jetbrains.idea.svn.portable.StatusClient; +import org.jetbrains.idea.svn.portable.SvnKitStatusClient; import org.jetbrains.idea.svn.portable.SvnkitSvnWcClient; import org.jetbrains.idea.svn.properties.SvnKitPropertyClient; import org.jetbrains.idea.svn.revert.SvnKitRevertClient; @@ -65,14 +65,14 @@ public class SvnKitClientFactory extends ClientFactory { myBrowseClient = new SvnKitBrowseClient(); myDiffClient = new SvnKitDiffClient(); myCheckinClient = new SvnKitCheckinClient(); - statusClient = new SvnkitSvnStatusClient(); + statusClient = new SvnKitStatusClient(); infoClient = new SvnkitSvnWcClient(myVcs); } @NotNull @Override - public SvnStatusClientI createStatusClient(@Nullable ISVNStatusFileProvider provider, @NotNull ISVNEventHandler handler) { - return prepare(new SvnkitSvnStatusClient(provider, handler)); + public StatusClient createStatusClient(@Nullable ISVNStatusFileProvider provider, @NotNull ISVNEventHandler handler) { + return prepare(new SvnKitStatusClient(provider, handler)); } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java index 7a344c8c171e..8443fda58409 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java @@ -29,7 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.commandLine.*; -import org.jetbrains.idea.svn.portable.SvnStatusClientI; +import org.jetbrains.idea.svn.portable.StatusClient; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; @@ -126,7 +126,7 @@ public class CmdCheckinClient extends BaseSvnClient implements CheckinClient { }.doFilter(ContainerUtil.newArrayList(committables)); if (!childrenOfSomebody.isEmpty()) { List result = ContainerUtil.newArrayList(); - SvnStatusClientI statusClient = myFactory.createStatusClient(); + StatusClient statusClient = myFactory.createStatusClient(); for (File file : committables) { if (!childrenOfSomebody.contains(file.getPath())) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdStatusClient.java similarity index 97% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdStatusClient.java index 1b31d152f07e..3ff1015ef144 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineStatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdStatusClient.java @@ -15,7 +15,6 @@ */ package org.jetbrains.idea.svn.commandLine; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Getter; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -28,7 +27,7 @@ import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.portable.PortableStatus; import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; -import org.jetbrains.idea.svn.portable.SvnStatusClientI; +import org.jetbrains.idea.svn.portable.StatusClient; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.wc.*; @@ -49,8 +48,7 @@ import java.util.*; * Date: 1/25/12 * Time: 5:21 PM */ -public class SvnCommandLineStatusClient extends BaseSvnClient implements SvnStatusClientI { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient"); +public class CmdStatusClient extends BaseSvnClient implements StatusClient { @Override public long doStatus(File path, boolean recursive, boolean remote, boolean reportAll, boolean includeIgnored, ISVNStatusHandler handler) @@ -184,7 +182,7 @@ public class SvnCommandLineStatusClient extends BaseSvnClient implements SvnStat CommandUtil.put(parameters, remote, "-u"); CommandUtil.put(parameters, reportAll, "--verbose"); CommandUtil.put(parameters, includeIgnored, "--no-ignore"); - // TODO: Fix this check - update corresponding parameters in SvnStatusClientI + // TODO: Fix this check - update corresponding parameters in StatusClient CommandUtil.putChangeLists(parameters, changeLists); parameters.add("--xml"); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnStatusClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/StatusClient.java similarity index 97% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnStatusClientI.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/portable/StatusClient.java index b7394da8d117..81444b3564ec 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnStatusClientI.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/StatusClient.java @@ -31,7 +31,7 @@ import java.util.Collection; * Date: 1/24/12 * Time: 9:46 AM */ -public interface SvnStatusClientI extends SvnClient { +public interface StatusClient extends SvnClient { long doStatus(File path, boolean recursive, boolean remote, boolean reportAll, boolean includeIgnored, ISVNStatusHandler handler) throws SVNException; long doStatus(File path, boolean recursive, boolean remote, boolean reportAll, boolean includeIgnored, boolean collectParentExternals, ISVNStatusHandler handler) throws SVNException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitStatusClient.java similarity index 94% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnStatusClient.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitStatusClient.java index a59283ab1091..dda9e81145b5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnStatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitStatusClient.java @@ -31,17 +31,17 @@ import java.util.Collection; * Date: 1/24/12 * Time: 9:47 AM */ -public class SvnkitSvnStatusClient extends BaseSvnClient implements SvnStatusClientI { +public class SvnKitStatusClient extends BaseSvnClient implements StatusClient { private SVNStatusClient myStatusClient; @Nullable private final ISVNStatusFileProvider myProvider; @Nullable private final ISVNEventHandler myHandler; - public SvnkitSvnStatusClient() { + public SvnKitStatusClient() { this(null, null); } - public SvnkitSvnStatusClient(@Nullable ISVNStatusFileProvider provider, @Nullable ISVNEventHandler handler) { + public SvnKitStatusClient(@Nullable ISVNStatusFileProvider provider, @Nullable ISVNEventHandler handler) { myProvider = provider; myHandler = handler; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java index 75f59ede34b3..71ce766cf249 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java @@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnRevisionNumber; import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.portable.SvnStatusClientI; +import org.jetbrains.idea.svn.portable.StatusClient; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.*; @@ -123,7 +123,7 @@ public class SvnTreeConflictResolver { } else { final Set usedToBeAdded = new HashSet(); if (myPath.isDirectory()) { - SvnStatusClientI statusClient = myVcs.getFactory(ioFile).createStatusClient(); + StatusClient statusClient = myVcs.getFactory(ioFile).createStatusClient(); statusClient.doStatus(ioFile, SVNRevision.UNDEFINED, SVNDepth.INFINITY, false, false, false, false, new ISVNStatusHandler() { @Override diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java index 5bf5d7651f94..b8bd1c9f4172 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java @@ -24,7 +24,7 @@ import com.intellij.util.containers.Convertor; import com.intellij.util.containers.MultiMap; import junit.framework.Assert; import junit.framework.TestCase; -import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient; +import org.jetbrains.idea.svn.commandLine.CmdStatusClient; import org.jetbrains.idea.svn.commandLine.SvnInfoHandler; import org.jetbrains.idea.svn.commandLine.SvnStatusHandler; import org.jetbrains.idea.svn.portable.IdeaSVNInfo; @@ -671,14 +671,17 @@ public class SvnParseCommandLineParseTest extends TestCase { final String basePath = "C:\\TestProjects\\sortedProjects\\Subversion\\local2\\sep12main\\main"; final SvnStatusHandler[] handler = new SvnStatusHandler[1]; final File baseFile = new File(basePath); - final SvnStatusHandler.ExternalDataCallback callback = SvnCommandLineStatusClient.createStatusCallback(new ISVNStatusHandler() { + final SvnStatusHandler.ExternalDataCallback callback = CmdStatusClient.createStatusCallback(new ISVNStatusHandler() { @Override public void handleStatus(SVNStatus status) throws SVNException { System.out.println(status.getURL()); - if (new File("C:\\TestProjects\\sortedProjects\\Subversion\\local2\\sep12main\\main\\slave\\src\\com\\slave\\MacMessagesParser.java").equals(status.getFile())) { + if (new File( + "C:\\TestProjects\\sortedProjects\\Subversion\\local2\\sep12main\\main\\slave\\src\\com\\slave\\MacMessagesParser.java") + .equals(status.getFile())) { Assert.assertEquals("http://external/src/com/slave/MacMessagesParser.java", status.getURL().toString()); } - if (new File("C:\\TestProjects\\sortedProjects\\Subversion\\local2\\sep12main\\main\\slave\\src\\com\\slave\\SomeOtherClass.java").equals(status.getFile())) { + if (new File("C:\\TestProjects\\sortedProjects\\Subversion\\local2\\sep12main\\main\\slave\\src\\com\\slave\\SomeOtherClass.java") + .equals(status.getFile())) { Assert.assertEquals("http://external/src/com/slave/SomeOtherClass.java", status.getURL().toString()); } } From 0d2131df497eec729a6d495f458ff826ecfdeac3 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 13:45:27 +0400 Subject: [PATCH 32/65] svn: Refactored CmdStatusClient - do not use CommandExecutor.myCommandLine directly (use corresponding CommandExecutor methods instead) --- .../org/jetbrains/idea/svn/commandLine/CmdStatusClient.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdStatusClient.java index 3ff1015ef144..c6e41fcce92a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdStatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdStatusClient.java @@ -26,8 +26,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.portable.PortableStatus; -import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; import org.jetbrains.idea.svn.portable.StatusClient; +import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.wc.*; @@ -119,7 +119,7 @@ public class CmdStatusClient extends BaseSvnClient implements StatusClient { if (StringUtil.isEmptyOrSpaces(result)) { throw new SVNException(SVNErrorMessage.create(SVNErrorCode.FS_GENERAL, "Status request returned nothing for command: " + - command.myCommandLine.getCommandLineString())); + command.getCommandText())); } try { From 3dac92058be66bf1e76dafe3876eeba209a94598 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 13:52:59 +0400 Subject: [PATCH 33/65] svn: "svn status" related classes moved to "org.jetbrains.idea.svn.status" package --- .../org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java | 2 +- .../src/org/jetbrains/idea/svn/SvnStatusConvertor.java | 2 +- .../org/jetbrains/idea/svn/actions/MarkResolvedAction.java | 2 +- .../src/org/jetbrains/idea/svn/api/ClientFactory.java | 2 +- .../src/org/jetbrains/idea/svn/api/CmdClientFactory.java | 2 +- .../org/jetbrains/idea/svn/api/SvnKitClientFactory.java | 4 ++-- .../org/jetbrains/idea/svn/checkin/CmdCheckinClient.java | 2 +- .../src/org/jetbrains/idea/svn/diff/CmdDiffClient.java | 1 + .../idea/svn/{commandLine => status}/CmdStatusClient.java | 7 ++++--- .../idea/svn/{portable => status}/PortableStatus.java | 3 +-- .../idea/svn/{portable => status}/StatusClient.java | 2 +- .../idea/svn/{portable => status}/SvnKitStatusClient.java | 3 ++- .../idea/svn/{commandLine => status}/SvnStatusHandler.java | 5 +++-- .../idea/svn/treeConflict/SvnTreeConflictResolver.java | 2 +- .../jetbrains/idea/svn/SvnParseCommandLineParseTest.java | 6 +++--- 15 files changed, 24 insertions(+), 21 deletions(-) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{commandLine => status}/CmdStatusClient.java (98%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{portable => status}/PortableStatus.java (99%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{portable => status}/StatusClient.java (98%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{portable => status}/SvnKitStatusClient.java (97%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{commandLine => status}/SvnStatusHandler.java (99%) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java index 65c953ddd7e6..45b28e34b3d0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java @@ -31,7 +31,7 @@ import com.intellij.util.Processor; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.portable.StatusClient; +import org.jetbrains.idea.svn.status.StatusClient; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java index 3c0d396657c7..84c316691c1e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java @@ -18,7 +18,7 @@ package org.jetbrains.idea.svn; import com.intellij.openapi.vcs.FileStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.portable.PortableStatus; +import org.jetbrains.idea.svn.status.PortableStatus; import org.tmatesoft.svn.core.wc.SVNStatus; import org.tmatesoft.svn.core.wc.SVNStatusType; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java index 73c7c579ba55..d20b5f14d6b5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkResolvedAction.java @@ -35,7 +35,7 @@ import org.jetbrains.idea.svn.SvnStatusUtil; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.conflict.ConflictClient; import org.jetbrains.idea.svn.dialogs.SelectFilesDialog; -import org.jetbrains.idea.svn.portable.StatusClient; +import org.jetbrains.idea.svn.status.StatusClient; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.*; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java index 7b21511a7ae5..a57440b7e44f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java @@ -20,7 +20,7 @@ import org.jetbrains.idea.svn.diff.DiffClient; import org.jetbrains.idea.svn.history.HistoryClient; import org.jetbrains.idea.svn.integrate.MergeClient; import org.jetbrains.idea.svn.lock.LockClient; -import org.jetbrains.idea.svn.portable.StatusClient; +import org.jetbrains.idea.svn.status.StatusClient; import org.jetbrains.idea.svn.portable.SvnWcClientI; import org.jetbrains.idea.svn.properties.PropertyClient; import org.jetbrains.idea.svn.revert.RevertClient; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java index 84e195f3326d..66f9246f5b3f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java @@ -11,7 +11,7 @@ import org.jetbrains.idea.svn.checkin.CmdImportClient; import org.jetbrains.idea.svn.checkout.CmdCheckoutClient; import org.jetbrains.idea.svn.checkout.CmdExportClient; import org.jetbrains.idea.svn.cleanup.CmdCleanupClient; -import org.jetbrains.idea.svn.commandLine.CmdStatusClient; +import org.jetbrains.idea.svn.status.CmdStatusClient; import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient; import org.jetbrains.idea.svn.conflict.CmdConflictClient; import org.jetbrains.idea.svn.content.CmdContentClient; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java index 3183fcf11c46..630ca8526afa 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java @@ -20,8 +20,8 @@ import org.jetbrains.idea.svn.diff.SvnKitDiffClient; import org.jetbrains.idea.svn.history.SvnKitHistoryClient; import org.jetbrains.idea.svn.integrate.SvnKitMergeClient; import org.jetbrains.idea.svn.lock.SvnKitLockClient; -import org.jetbrains.idea.svn.portable.StatusClient; -import org.jetbrains.idea.svn.portable.SvnKitStatusClient; +import org.jetbrains.idea.svn.status.StatusClient; +import org.jetbrains.idea.svn.status.SvnKitStatusClient; import org.jetbrains.idea.svn.portable.SvnkitSvnWcClient; import org.jetbrains.idea.svn.properties.SvnKitPropertyClient; import org.jetbrains.idea.svn.revert.SvnKitRevertClient; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java index 8443fda58409..8b593a84ac12 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java @@ -29,7 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.commandLine.*; -import org.jetbrains.idea.svn.portable.StatusClient; +import org.jetbrains.idea.svn.status.StatusClient; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java index b774fe6b4aac..78b0e07837d4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java @@ -30,6 +30,7 @@ import org.jetbrains.idea.svn.SvnStatusConvertor; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.commandLine.*; import org.jetbrains.idea.svn.history.SvnRepositoryContentRevision; +import org.jetbrains.idea.svn.status.SvnStatusHandler; import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.wc.SVNRevision; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java similarity index 98% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdStatusClient.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java index c6e41fcce92a..6c37bedae982 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdStatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.commandLine; +package org.jetbrains.idea.svn.status; import com.intellij.openapi.util.Getter; import com.intellij.openapi.util.io.FileUtil; @@ -25,8 +25,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.api.BaseSvnClient; -import org.jetbrains.idea.svn.portable.PortableStatus; -import org.jetbrains.idea.svn.portable.StatusClient; +import org.jetbrains.idea.svn.commandLine.CommandExecutor; +import org.jetbrains.idea.svn.commandLine.CommandUtil; +import org.jetbrains.idea.svn.commandLine.SvnCommandName; import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/PortableStatus.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/PortableStatus.java similarity index 99% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/portable/PortableStatus.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/status/PortableStatus.java index b00cb42e8afe..e78c0cd57316 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/PortableStatus.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/PortableStatus.java @@ -13,11 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.portable; +package org.jetbrains.idea.svn.status; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Getter; -import org.jetbrains.idea.svn.WorkingCopyFormat; import org.tmatesoft.svn.core.SVNLock; import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.SVNURL; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/StatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/StatusClient.java similarity index 98% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/portable/StatusClient.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/status/StatusClient.java index 81444b3564ec..4b43e6c51211 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/StatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/StatusClient.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.portable; +package org.jetbrains.idea.svn.status; import org.jetbrains.idea.svn.api.SvnClient; import org.tmatesoft.svn.core.SVNDepth; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/SvnKitStatusClient.java similarity index 97% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitStatusClient.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/status/SvnKitStatusClient.java index dda9e81145b5..6f4ae27fc1e7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitStatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/SvnKitStatusClient.java @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.portable; +package org.jetbrains.idea.svn.status; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.jetbrains.idea.svn.status.StatusClient; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.*; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/SvnStatusHandler.java similarity index 99% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/status/SvnStatusHandler.java index 460f7cde959a..daa5f4f24128 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/SvnStatusHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.commandLine; +package org.jetbrains.idea.svn.status; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Getter; @@ -23,7 +23,8 @@ import com.intellij.util.containers.Convertor; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.portable.PortableStatus; +import org.jetbrains.idea.svn.commandLine.CommandUtil; +import org.jetbrains.idea.svn.commandLine.SVNLockWrapper; import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.internal.util.SVNDate; import org.tmatesoft.svn.core.wc.SVNInfo; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java index 71ce766cf249..c637ce243981 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java @@ -27,7 +27,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnRevisionNumber; import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.portable.StatusClient; +import org.jetbrains.idea.svn.status.StatusClient; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.*; diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java index b8bd1c9f4172..b5a82c2997e7 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java @@ -24,11 +24,11 @@ import com.intellij.util.containers.Convertor; import com.intellij.util.containers.MultiMap; import junit.framework.Assert; import junit.framework.TestCase; -import org.jetbrains.idea.svn.commandLine.CmdStatusClient; +import org.jetbrains.idea.svn.status.CmdStatusClient; import org.jetbrains.idea.svn.commandLine.SvnInfoHandler; -import org.jetbrains.idea.svn.commandLine.SvnStatusHandler; +import org.jetbrains.idea.svn.status.SvnStatusHandler; import org.jetbrains.idea.svn.portable.IdeaSVNInfo; -import org.jetbrains.idea.svn.portable.PortableStatus; +import org.jetbrains.idea.svn.status.PortableStatus; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNNodeKind; From c0dd0027c724125522de125bb298b6450cb2c68d Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 14:00:55 +0400 Subject: [PATCH 34/65] svn: Refactored SvnCommandLineInfoClient - do not inherit SvnkitSvnWcClient (just implement corresponding SvnWcClientI interface) --- .../idea/svn/commandLine/SvnCommandLineInfoClient.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java index 8f4cae8f313c..1c5ace204626 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java @@ -28,7 +28,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; -import org.jetbrains.idea.svn.portable.SvnkitSvnWcClient; +import org.jetbrains.idea.svn.portable.SvnWcClientI; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.ISVNInfoHandler; import org.tmatesoft.svn.core.wc.SVNInfo; @@ -52,14 +52,13 @@ import java.util.List; * Date: 1/27/12 * Time: 12:59 PM */ -public class SvnCommandLineInfoClient extends SvnkitSvnWcClient { +public class SvnCommandLineInfoClient implements SvnWcClientI { private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient"); @NotNull private final SvnVcs myVcs; public SvnCommandLineInfoClient(@NotNull final SvnVcs vcs) { - super(vcs); myVcs = vcs; } From 063575b6356726b7418fb5cf328518bcd1faac56 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 14:11:55 +0400 Subject: [PATCH 35/65] svn: Make info clients (both for SVNKit and command line) satisfy common client factory model --- .../jetbrains/idea/svn/api/ClientFactory.java | 3 +-- .../idea/svn/api/CmdClientFactory.java | 2 +- .../idea/svn/api/SvnKitClientFactory.java | 2 +- .../commandLine/SvnCommandLineInfoClient.java | 10 ++-------- .../idea/svn/portable/SvnMarkerInterface.java | 10 ---------- .../idea/svn/portable/SvnWcClientI.java | 11 ++++++++--- .../idea/svn/portable/SvnkitSvnWcClient.java | 19 +++++++++---------- .../idea/svn/update/CmdUpdateClient.java | 4 +--- 8 files changed, 23 insertions(+), 38 deletions(-) delete mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnMarkerInterface.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java index a57440b7e44f..711e98cab36f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java @@ -107,8 +107,7 @@ public abstract class ClientFactory { @NotNull public SvnWcClientI createInfoClient() { - // TODO: Update this in same like other clients - move to corresponding package, rename clients - return infoClient; + return prepare(infoClient); } // TODO: Update this in same like other clients - move to corresponding package, rename clients diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java index 66f9246f5b3f..95d1e3e520b3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java @@ -62,7 +62,7 @@ public class CmdClientFactory extends ClientFactory { myDiffClient = new CmdDiffClient(); myCheckinClient = new CmdCheckinClient(); statusClient = new CmdStatusClient(); - infoClient = new SvnCommandLineInfoClient(myVcs); + infoClient = new SvnCommandLineInfoClient(); } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java index 630ca8526afa..14be260b5843 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java @@ -66,7 +66,7 @@ public class SvnKitClientFactory extends ClientFactory { myDiffClient = new SvnKitDiffClient(); myCheckinClient = new SvnKitCheckinClient(); statusClient = new SvnKitStatusClient(); - infoClient = new SvnkitSvnWcClient(myVcs); + infoClient = new SvnkitSvnWcClient(); } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java index 1c5ace204626..8348eed2073f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java @@ -26,7 +26,7 @@ import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnVcs; +import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; import org.jetbrains.idea.svn.portable.SvnWcClientI; import org.tmatesoft.svn.core.*; @@ -52,16 +52,10 @@ import java.util.List; * Date: 1/27/12 * Time: 12:59 PM */ -public class SvnCommandLineInfoClient implements SvnWcClientI { +public class SvnCommandLineInfoClient extends BaseSvnClient implements SvnWcClientI { private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient"); - @NotNull private final SvnVcs myVcs; - - public SvnCommandLineInfoClient(@NotNull final SvnVcs vcs) { - myVcs = vcs; - } - @Override public void doInfo(File path, SVNRevision revision, boolean recursive, ISVNInfoHandler handler) throws SVNException { doInfo(path, SVNRevision.UNDEFINED, revision, recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY, null, handler); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnMarkerInterface.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnMarkerInterface.java deleted file mode 100644 index c043188a990f..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnMarkerInterface.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.jetbrains.idea.svn.portable; - -/** - * Created with IntelliJ IDEA. - * User: Irina.Chernushina - * Date: 10/19/12 - * Time: 3:48 PM - */ -public interface SvnMarkerInterface { -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java index 48ba32e5357d..edefd63de2d6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java @@ -17,8 +17,13 @@ package org.jetbrains.idea.svn.portable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.wc.*; +import org.jetbrains.idea.svn.api.SvnClient; +import org.tmatesoft.svn.core.SVNDepth; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.wc.ISVNInfoHandler; +import org.tmatesoft.svn.core.wc.SVNInfo; +import org.tmatesoft.svn.core.wc.SVNRevision; import java.io.File; import java.util.Collection; @@ -29,7 +34,7 @@ import java.util.Collection; * Date: 1/20/12 * Time: 6:54 PM */ -public interface SvnWcClientI extends SvnMarkerInterface { +public interface SvnWcClientI extends SvnClient { void doInfo(File path, SVNRevision revision, boolean recursive, ISVNInfoHandler handler) throws SVNException; void doInfo(File path, SVNRevision pegRevision, SVNRevision revision, boolean recursive, ISVNInfoHandler handler) throws SVNException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java index 44cca7fa26c8..c031722dd413 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java @@ -17,9 +17,14 @@ package org.jetbrains.idea.svn.portable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnVcs; -import org.tmatesoft.svn.core.*; -import org.tmatesoft.svn.core.wc.*; +import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.tmatesoft.svn.core.SVNDepth; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.wc.ISVNInfoHandler; +import org.tmatesoft.svn.core.wc.SVNInfo; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNWCClient; import java.io.File; import java.util.Collection; @@ -30,13 +35,7 @@ import java.util.Collection; * Date: 1/20/12 * Time: 6:55 PM */ -public class SvnkitSvnWcClient implements SvnWcClientI { - @NotNull - private final SvnVcs myVcs; - - public SvnkitSvnWcClient(@NotNull SvnVcs vcs) { - myVcs = vcs; - } +public class SvnkitSvnWcClient extends BaseSvnClient implements SvnWcClientI { public SVNWCClient getClient() { return myVcs.createWCClient(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java index a6a4d0f2095f..7ccc9a507c63 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java @@ -21,7 +21,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.commandLine.BaseUpdateCommandListener; import org.jetbrains.idea.svn.commandLine.CommandUtil; -import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient; import org.jetbrains.idea.svn.commandLine.SvnCommandName; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.SVNEvent; @@ -65,8 +64,7 @@ public class CmdUpdateClient extends SvnKitUpdateClient { } private void checkWorkingCopy(@NotNull File path) throws SVNException { - final SvnCommandLineInfoClient infoClient = new SvnCommandLineInfoClient(myVcs); - final SVNInfo info = infoClient.doInfo(path, SVNRevision.UNDEFINED); + final SVNInfo info = myFactory.createInfoClient().doInfo(path, SVNRevision.UNDEFINED); if (info == null || info.getURL() == null) { throw new SVNException(SVNErrorMessage.create(SVNErrorCode.WC_NOT_WORKING_COPY, path.getPath())); From 93f8c1d177c5e7e60180535dbaa48ec4a50a098e Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 14:15:19 +0400 Subject: [PATCH 36/65] svn: Renamed info clients for both SVNKit and command line (interface and implementations) --- .../src/org/jetbrains/idea/svn/api/ClientFactory.java | 6 +++--- .../src/org/jetbrains/idea/svn/api/CmdClientFactory.java | 4 ++-- .../org/jetbrains/idea/svn/api/SvnKitClientFactory.java | 4 ++-- .../{SvnCommandLineInfoClient.java => CmdInfoClient.java} | 8 ++++---- .../svn/portable/{SvnWcClientI.java => InfoClient.java} | 2 +- .../{SvnkitSvnWcClient.java => SvnKitInfoClient.java} | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) rename plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/{SvnCommandLineInfoClient.java => CmdInfoClient.java} (97%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/portable/{SvnWcClientI.java => InfoClient.java} (97%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/portable/{SvnkitSvnWcClient.java => SvnKitInfoClient.java} (97%) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java index 711e98cab36f..6d5f31e59116 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java @@ -20,8 +20,8 @@ import org.jetbrains.idea.svn.diff.DiffClient; import org.jetbrains.idea.svn.history.HistoryClient; import org.jetbrains.idea.svn.integrate.MergeClient; import org.jetbrains.idea.svn.lock.LockClient; +import org.jetbrains.idea.svn.portable.InfoClient; import org.jetbrains.idea.svn.status.StatusClient; -import org.jetbrains.idea.svn.portable.SvnWcClientI; import org.jetbrains.idea.svn.properties.PropertyClient; import org.jetbrains.idea.svn.revert.RevertClient; import org.jetbrains.idea.svn.update.RelocateClient; @@ -45,7 +45,7 @@ public abstract class ClientFactory { protected RevertClient revertClient; protected DeleteClient deleteClient; protected StatusClient statusClient; - protected SvnWcClientI infoClient; + protected InfoClient infoClient; protected CopyMoveClient copyMoveClient; protected ConflictClient conflictClient; protected PropertyClient propertyClient; @@ -106,7 +106,7 @@ public abstract class ClientFactory { } @NotNull - public SvnWcClientI createInfoClient() { + public InfoClient createInfoClient() { return prepare(infoClient); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java index 95d1e3e520b3..62a99dc26eb7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java @@ -12,7 +12,7 @@ import org.jetbrains.idea.svn.checkout.CmdCheckoutClient; import org.jetbrains.idea.svn.checkout.CmdExportClient; import org.jetbrains.idea.svn.cleanup.CmdCleanupClient; import org.jetbrains.idea.svn.status.CmdStatusClient; -import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient; +import org.jetbrains.idea.svn.commandLine.CmdInfoClient; import org.jetbrains.idea.svn.conflict.CmdConflictClient; import org.jetbrains.idea.svn.content.CmdContentClient; import org.jetbrains.idea.svn.copy.CmdCopyMoveClient; @@ -62,7 +62,7 @@ public class CmdClientFactory extends ClientFactory { myDiffClient = new CmdDiffClient(); myCheckinClient = new CmdCheckinClient(); statusClient = new CmdStatusClient(); - infoClient = new SvnCommandLineInfoClient(); + infoClient = new CmdInfoClient(); } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java index 14be260b5843..dca8a1256517 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java @@ -22,7 +22,7 @@ import org.jetbrains.idea.svn.integrate.SvnKitMergeClient; import org.jetbrains.idea.svn.lock.SvnKitLockClient; import org.jetbrains.idea.svn.status.StatusClient; import org.jetbrains.idea.svn.status.SvnKitStatusClient; -import org.jetbrains.idea.svn.portable.SvnkitSvnWcClient; +import org.jetbrains.idea.svn.portable.SvnKitInfoClient; import org.jetbrains.idea.svn.properties.SvnKitPropertyClient; import org.jetbrains.idea.svn.revert.SvnKitRevertClient; import org.jetbrains.idea.svn.update.SvnKitRelocateClient; @@ -66,7 +66,7 @@ public class SvnKitClientFactory extends ClientFactory { myDiffClient = new SvnKitDiffClient(); myCheckinClient = new SvnKitCheckinClient(); statusClient = new SvnKitStatusClient(); - infoClient = new SvnkitSvnWcClient(); + infoClient = new SvnKitInfoClient(); } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdInfoClient.java similarity index 97% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdInfoClient.java index 8348eed2073f..b5f36d87de5a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdInfoClient.java @@ -27,8 +27,8 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.jetbrains.idea.svn.portable.InfoClient; import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; -import org.jetbrains.idea.svn.portable.SvnWcClientI; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.ISVNInfoHandler; import org.tmatesoft.svn.core.wc.SVNInfo; @@ -52,9 +52,9 @@ import java.util.List; * Date: 1/27/12 * Time: 12:59 PM */ -public class SvnCommandLineInfoClient extends BaseSvnClient implements SvnWcClientI { +public class CmdInfoClient extends BaseSvnClient implements InfoClient { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient"); + private static final Logger LOG = Logger.getInstance(CmdInfoClient.class); @Override public void doInfo(File path, SVNRevision revision, boolean recursive, ISVNInfoHandler handler) throws SVNException { @@ -91,7 +91,7 @@ public class SvnCommandLineInfoClient extends BaseSvnClient implements SvnWcClie List parameters = new ArrayList(); fillParameters(path.getAbsolutePath(), pegRevision, revision, depth, parameters); - // TODO: Fix this check - update corresponding parameters in SvnWcClientI + // TODO: Fix this check - update corresponding parameters in InfoClient CommandUtil.putChangeLists(parameters, changeLists); parseResult(handler, base, execute(parameters, path)); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoClient.java similarity index 97% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoClient.java index edefd63de2d6..6508981501a8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoClient.java @@ -34,7 +34,7 @@ import java.util.Collection; * Date: 1/20/12 * Time: 6:54 PM */ -public interface SvnWcClientI extends SvnClient { +public interface InfoClient extends SvnClient { void doInfo(File path, SVNRevision revision, boolean recursive, ISVNInfoHandler handler) throws SVNException; void doInfo(File path, SVNRevision pegRevision, SVNRevision revision, boolean recursive, ISVNInfoHandler handler) throws SVNException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitInfoClient.java similarity index 97% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitInfoClient.java index c031722dd413..5268de208f67 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitInfoClient.java @@ -35,7 +35,7 @@ import java.util.Collection; * Date: 1/20/12 * Time: 6:55 PM */ -public class SvnkitSvnWcClient extends BaseSvnClient implements SvnWcClientI { +public class SvnKitInfoClient extends BaseSvnClient implements InfoClient { public SVNWCClient getClient() { return myVcs.createWCClient(); From 5e4c305100d75aa5dbcf5043653a83f291bc6e03 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 14:24:18 +0400 Subject: [PATCH 37/65] svn: "svn info" related classes moved to "org.jetbrains.idea.svn.info" package --- .../src/org/jetbrains/idea/svn/api/ClientFactory.java | 2 +- .../src/org/jetbrains/idea/svn/api/CmdClientFactory.java | 2 +- .../src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java | 2 +- .../idea/svn/{commandLine => info}/CmdInfoClient.java | 4 ++-- .../jetbrains/idea/svn/{portable => info}/IdeaSVNInfo.java | 2 +- .../org/jetbrains/idea/svn/{portable => info}/InfoClient.java | 2 +- .../idea/svn/{commandLine => info}/SVNLockWrapper.java | 2 +- .../idea/svn/{commandLine => info}/SvnInfoHandler.java | 3 ++- .../idea/svn/{commandLine => info}/SvnInfoStructure.java | 3 +-- .../idea/svn/{portable => info}/SvnKitInfoClient.java | 3 ++- .../src/org/jetbrains/idea/svn/status/SvnStatusHandler.java | 2 +- .../org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java | 4 ++-- 12 files changed, 16 insertions(+), 15 deletions(-) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{commandLine => info}/CmdInfoClient.java (99%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{portable => info}/IdeaSVNInfo.java (98%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{portable => info}/InfoClient.java (98%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{commandLine => info}/SVNLockWrapper.java (98%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{commandLine => info}/SvnInfoHandler.java (99%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{commandLine => info}/SvnInfoStructure.java (98%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{portable => info}/SvnKitInfoClient.java (97%) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java index 6d5f31e59116..1021ad4d796c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java @@ -20,7 +20,7 @@ import org.jetbrains.idea.svn.diff.DiffClient; import org.jetbrains.idea.svn.history.HistoryClient; import org.jetbrains.idea.svn.integrate.MergeClient; import org.jetbrains.idea.svn.lock.LockClient; -import org.jetbrains.idea.svn.portable.InfoClient; +import org.jetbrains.idea.svn.info.InfoClient; import org.jetbrains.idea.svn.status.StatusClient; import org.jetbrains.idea.svn.properties.PropertyClient; import org.jetbrains.idea.svn.revert.RevertClient; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java index 62a99dc26eb7..13e231345b43 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java @@ -12,7 +12,7 @@ import org.jetbrains.idea.svn.checkout.CmdCheckoutClient; import org.jetbrains.idea.svn.checkout.CmdExportClient; import org.jetbrains.idea.svn.cleanup.CmdCleanupClient; import org.jetbrains.idea.svn.status.CmdStatusClient; -import org.jetbrains.idea.svn.commandLine.CmdInfoClient; +import org.jetbrains.idea.svn.info.CmdInfoClient; import org.jetbrains.idea.svn.conflict.CmdConflictClient; import org.jetbrains.idea.svn.content.CmdContentClient; import org.jetbrains.idea.svn.copy.CmdCopyMoveClient; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java index dca8a1256517..89039348530b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java @@ -22,7 +22,7 @@ import org.jetbrains.idea.svn.integrate.SvnKitMergeClient; import org.jetbrains.idea.svn.lock.SvnKitLockClient; import org.jetbrains.idea.svn.status.StatusClient; import org.jetbrains.idea.svn.status.SvnKitStatusClient; -import org.jetbrains.idea.svn.portable.SvnKitInfoClient; +import org.jetbrains.idea.svn.info.SvnKitInfoClient; import org.jetbrains.idea.svn.properties.SvnKitPropertyClient; import org.jetbrains.idea.svn.revert.SvnKitRevertClient; import org.jetbrains.idea.svn.update.SvnKitRelocateClient; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java similarity index 99% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdInfoClient.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java index b5f36d87de5a..70b07e3a9255 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CmdInfoClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.commandLine; +package org.jetbrains.idea.svn.info; import com.intellij.execution.process.ProcessOutput; import com.intellij.execution.process.ProcessOutputTypes; @@ -27,7 +27,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; -import org.jetbrains.idea.svn.portable.InfoClient; +import org.jetbrains.idea.svn.commandLine.*; import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.ISVNInfoHandler; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/IdeaSVNInfo.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/IdeaSVNInfo.java similarity index 98% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/portable/IdeaSVNInfo.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/info/IdeaSVNInfo.java index 7acc08c7318c..0e2905e73016 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/IdeaSVNInfo.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/IdeaSVNInfo.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.portable; +package org.jetbrains.idea.svn.info; import org.jetbrains.annotations.Nullable; import org.tmatesoft.svn.core.SVNDepth; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/InfoClient.java similarity index 98% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoClient.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/info/InfoClient.java index 6508981501a8..f6582e603eda 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/InfoClient.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.portable; +package org.jetbrains.idea.svn.info; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SVNLockWrapper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/SVNLockWrapper.java similarity index 98% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SVNLockWrapper.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/info/SVNLockWrapper.java index 7cc4e24e4fa9..f5752074da77 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SVNLockWrapper.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/SVNLockWrapper.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.commandLine; +package org.jetbrains.idea.svn.info; import org.tmatesoft.svn.core.SVNLock; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/SvnInfoHandler.java similarity index 99% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/info/SvnInfoHandler.java index 46372c2a3ec2..7548ca1c193e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/SvnInfoHandler.java @@ -13,13 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.commandLine; +package org.jetbrains.idea.svn.info; import com.intellij.openapi.util.Getter; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Consumer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNNodeKind; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/SvnInfoStructure.java similarity index 98% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/info/SvnInfoStructure.java index 696e366490d7..6e1b1db1efa2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/SvnInfoStructure.java @@ -13,12 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.commandLine; +package org.jetbrains.idea.svn.info; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.portable.IdeaSVNInfo; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.wc.SVNConflictVersion; import org.tmatesoft.svn.core.wc.*; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/SvnKitInfoClient.java similarity index 97% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitInfoClient.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/info/SvnKitInfoClient.java index 5268de208f67..4cefde21d9c8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnKitInfoClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/SvnKitInfoClient.java @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.portable; +package org.jetbrains.idea.svn.info; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.jetbrains.idea.svn.info.InfoClient; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/SvnStatusHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/SvnStatusHandler.java index daa5f4f24128..e5e9be5c554f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/SvnStatusHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/SvnStatusHandler.java @@ -24,7 +24,7 @@ import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.commandLine.CommandUtil; -import org.jetbrains.idea.svn.commandLine.SVNLockWrapper; +import org.jetbrains.idea.svn.info.SVNLockWrapper; import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.internal.util.SVNDate; import org.tmatesoft.svn.core.wc.SVNInfo; diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java index b5a82c2997e7..ec78b9fd5f55 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnParseCommandLineParseTest.java @@ -25,9 +25,9 @@ import com.intellij.util.containers.MultiMap; import junit.framework.Assert; import junit.framework.TestCase; import org.jetbrains.idea.svn.status.CmdStatusClient; -import org.jetbrains.idea.svn.commandLine.SvnInfoHandler; +import org.jetbrains.idea.svn.info.SvnInfoHandler; import org.jetbrains.idea.svn.status.SvnStatusHandler; -import org.jetbrains.idea.svn.portable.IdeaSVNInfo; +import org.jetbrains.idea.svn.info.IdeaSVNInfo; import org.jetbrains.idea.svn.status.PortableStatus; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; From 42bc957fd4956110dd637bf71109b4764e40ac7d Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 14:31:02 +0400 Subject: [PATCH 38/65] svn: Several classes moved to corresponding packages (commit related and exception classes) --- .../svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java | 2 +- .../org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java | 2 +- .../src/org/jetbrains/idea/svn/checkin/CmdImportClient.java | 1 - .../idea/svn/{commandLine => checkin}/CommitEventHandler.java | 2 +- .../idea/svn/{commandLine => checkin}/CommitEventType.java | 2 +- .../src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java | 2 -- .../src/org/jetbrains/idea/svn/checkin/ImportClient.java | 1 - .../src/org/jetbrains/idea/svn/checkin/SvnKitImportClient.java | 1 - .../org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java | 2 +- .../idea/svn/{portable => commandLine}/SvnExceptionWrapper.java | 2 +- .../src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java | 1 + .../src/org/jetbrains/idea/svn/copy/CopyMoveClient.java | 2 +- .../src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java | 2 +- .../svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java | 2 +- .../src/org/jetbrains/idea/svn/status/CmdStatusClient.java | 2 +- 15 files changed, 11 insertions(+), 15 deletions(-) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{commandLine => checkin}/CommitEventHandler.java (95%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{commandLine => checkin}/CommitEventType.java (96%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{portable => commandLine}/SvnExceptionWrapper.java (97%) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java index 85bc9b1a7f02..3b0195e6079d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnChangeProvider.java @@ -34,7 +34,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.EventDispatcher; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.actions.CleanupWorker; -import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; +import org.jetbrains.idea.svn.commandLine.SvnExceptionWrapper; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java index 43b0a479d089..c0b06f838293 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java @@ -36,7 +36,7 @@ import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnStatusUtil; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.checkin.IdeaCommitHandler; -import org.jetbrains.idea.svn.commandLine.CommitEventHandler; +import org.jetbrains.idea.svn.checkin.CommitEventHandler; import org.jetbrains.idea.svn.dialogs.CreateBranchOrTagDialog; import org.jetbrains.idea.svn.update.AutoSvnUpdater; import org.jetbrains.idea.svn.update.SingleRootSwitcher; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java index e78cf6aa0428..ee13f1c0de28 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java @@ -5,7 +5,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.commandLine.CommandUtil; -import org.jetbrains.idea.svn.commandLine.CommitEventHandler; import org.jetbrains.idea.svn.commandLine.SvnCommandName; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNURL; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CommitEventHandler.java similarity index 95% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventHandler.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CommitEventHandler.java index 7effc83352ae..87be3fae7dd5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CommitEventHandler.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.commandLine; +package org.jetbrains.idea.svn.checkin; import org.tmatesoft.svn.core.wc.ISVNEventHandler; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventType.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CommitEventType.java similarity index 96% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventType.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CommitEventType.java index f64bf745fa08..6fdd9a0b8229 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommitEventType.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CommitEventType.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.commandLine; +package org.jetbrains.idea.svn.checkin; /** * Created with IntelliJ IDEA. diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java index b53492013ef1..3b78ac667efa 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaCommitHandler.java @@ -28,8 +28,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnUtil; -import org.jetbrains.idea.svn.commandLine.CommitEventHandler; -import org.jetbrains.idea.svn.commandLine.CommitEventType; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNEvent; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/ImportClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/ImportClient.java index 2a8a549ab283..d3c273ee1449 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/ImportClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/ImportClient.java @@ -4,7 +4,6 @@ import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.SvnClient; -import org.jetbrains.idea.svn.commandLine.CommitEventHandler; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.ISVNCommitHandler; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitImportClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitImportClient.java index 838e7646a310..e2ee8d988bd4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitImportClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitImportClient.java @@ -4,7 +4,6 @@ import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; -import org.jetbrains.idea.svn.commandLine.CommitEventHandler; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java index 92d964e3a208..634d528c17f1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/SvnCheckoutProvider.java @@ -45,7 +45,7 @@ import org.jetbrains.idea.svn.actions.ExclusiveBackgroundVcsAction; import org.jetbrains.idea.svn.actions.SvnExcludingIgnoredOperation; import org.jetbrains.idea.svn.api.ClientFactory; import org.jetbrains.idea.svn.checkin.IdeaCommitHandler; -import org.jetbrains.idea.svn.commandLine.CommitEventHandler; +import org.jetbrains.idea.svn.checkin.CommitEventHandler; import org.jetbrains.idea.svn.dialogs.CheckoutDialog; import org.jetbrains.idea.svn.dialogs.UpgradeFormatDialog; import org.tmatesoft.svn.core.SVNCancelException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnExceptionWrapper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnExceptionWrapper.java similarity index 97% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnExceptionWrapper.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnExceptionWrapper.java index d9c6202d23a6..cd451e149d09 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnExceptionWrapper.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnExceptionWrapper.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.portable; +package org.jetbrains.idea.svn.commandLine; import org.tmatesoft.svn.core.SVNException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java index 692724dd72e8..952001c2801e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java @@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.checkin.CmdCheckinClient; +import org.jetbrains.idea.svn.checkin.CommitEventHandler; import org.jetbrains.idea.svn.commandLine.*; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNRevision; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CopyMoveClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CopyMoveClient.java index e8f49d869ba4..8fb3cf4af573 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CopyMoveClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CopyMoveClient.java @@ -4,7 +4,7 @@ import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.SvnClient; -import org.jetbrains.idea.svn.commandLine.CommitEventHandler; +import org.jetbrains.idea.svn.checkin.CommitEventHandler; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java index 1f9f7d9b8fe1..6a600a1fcc55 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java @@ -4,7 +4,7 @@ import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; -import org.jetbrains.idea.svn.commandLine.CommitEventHandler; +import org.jetbrains.idea.svn.checkin.CommitEventHandler; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java index 70b07e3a9255..fdd28902bb6a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java @@ -28,7 +28,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.commandLine.*; -import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; +import org.jetbrains.idea.svn.commandLine.SvnExceptionWrapper; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.ISVNInfoHandler; import org.tmatesoft.svn.core.wc.SVNInfo; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java index 6c37bedae982..b463d2f6ba27 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java @@ -28,7 +28,7 @@ import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.commandLine.CommandExecutor; import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.jetbrains.idea.svn.commandLine.SvnCommandName; -import org.jetbrains.idea.svn.portable.SvnExceptionWrapper; +import org.jetbrains.idea.svn.commandLine.SvnExceptionWrapper; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.wc.*; From 225551399a3053ee063f081c308f2d9db542e616 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 14:45:09 +0400 Subject: [PATCH 39/65] svn: Moved execute() methods from CommandUtil to BaseSvnClient --- .../jetbrains/idea/svn/add/CmdAddClient.java | 2 +- .../idea/svn/annotate/CmdAnnotateClient.java | 2 +- .../jetbrains/idea/svn/api/BaseSvnClient.java | 40 ++++++++++++++++++- .../idea/svn/browse/CmdBrowseClient.java | 2 +- .../idea/svn/change/CmdChangeListClient.java | 4 +- .../idea/svn/checkin/CmdCheckinClient.java | 2 +- .../idea/svn/checkin/CmdImportClient.java | 2 +- .../idea/svn/checkout/CmdCheckoutClient.java | 2 +- .../idea/svn/checkout/CmdExportClient.java | 2 +- .../idea/svn/cleanup/CmdCleanupClient.java | 2 +- .../idea/svn/commandLine/CommandUtil.java | 36 ----------------- .../idea/svn/conflict/CmdConflictClient.java | 2 +- .../idea/svn/content/CmdContentClient.java | 2 +- .../idea/svn/copy/CmdCopyMoveClient.java | 7 ++-- .../idea/svn/delete/CmdDeleteClient.java | 2 +- .../idea/svn/diff/CmdDiffClient.java | 2 +- .../idea/svn/history/CmdHistoryClient.java | 2 +- .../idea/svn/info/CmdInfoClient.java | 4 +- .../idea/svn/integrate/CmdMergeClient.java | 2 +- .../idea/svn/lock/CmdLockClient.java | 4 +- .../svn/properties/CmdPropertyClient.java | 11 +++-- .../idea/svn/revert/CmdRevertClient.java | 2 +- .../idea/svn/status/CmdStatusClient.java | 2 +- .../idea/svn/update/CmdRelocateClient.java | 2 +- .../idea/svn/update/CmdUpdateClient.java | 2 +- .../idea/svn/upgrade/CmdUpgradeClient.java | 2 +- .../idea/svn/SvnCommandLineStabilityTest.java | 4 +- 27 files changed, 74 insertions(+), 74 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/add/CmdAddClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/add/CmdAddClient.java index adbc3f6437b0..4811e3286d70 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/add/CmdAddClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/add/CmdAddClient.java @@ -43,7 +43,7 @@ public class CmdAddClient extends BaseSvnClient implements AddClient { // TODO: handler should be called in parallel with command execution, but this will be in other thread // TODO: check if that is ok for current handler implementation // TODO: add possibility to invoke "handler.checkCancelled" - process should be killed - CommandExecutor command = CommandUtil.execute(myVcs, SvnTarget.fromFile(file), SvnCommandName.add, parameters, null); + CommandExecutor command = execute(myVcs, SvnTarget.fromFile(file), SvnCommandName.add, parameters, null); FileStatusResultParser parser = new FileStatusResultParser(CHANGED_PATH, handler, new AddStatusConvertor()); parser.parse(command.getOutput()); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/CmdAnnotateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/CmdAnnotateClient.java index 23c75a73dd86..5cb18a35fc5c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/CmdAnnotateClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/CmdAnnotateClient.java @@ -42,7 +42,7 @@ public class CmdAnnotateClient extends BaseSvnClient implements AnnotateClient { CommandUtil.put(parameters, diffOptions); parameters.add("--xml"); - CommandExecutor command = CommandUtil.execute(myVcs, target, SvnCommandName.blame, parameters, null); + CommandExecutor command = execute(myVcs, target, SvnCommandName.blame, parameters, null); parseOutput(command.getOutput(), handler); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java index e140a62db91f..9403c4602bfe 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java @@ -6,7 +6,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.WorkingCopyFormat; -import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback; +import org.jetbrains.idea.svn.commandLine.*; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNEvent; @@ -15,6 +16,7 @@ import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; import java.util.Collection; +import java.util.List; /** * @author Konstantin Kolosovsky. @@ -71,6 +73,42 @@ public abstract class BaseSvnClient implements SvnClient { } } + /** + * Utility method for running commands. + * // TODO: Should be replaced with non-static analogue. + * + * @param vcs + * @param target + * @param name + * @param parameters + * @param listener + * @throws com.intellij.openapi.vcs.VcsException + */ + public static CommandExecutor execute(@NotNull SvnVcs vcs, + @NotNull SvnTarget target, + @NotNull SvnCommandName name, + @NotNull List parameters, + @Nullable LineCommandListener listener) throws VcsException { + return execute(vcs, target, null, name, parameters, listener); + } + + public static CommandExecutor execute(@NotNull SvnVcs vcs, + @NotNull SvnTarget target, + @Nullable File workingDirectory, + @NotNull SvnCommandName name, + @NotNull List parameters, + @Nullable LineCommandListener listener) throws VcsException { + Command command = new Command(name); + + command.setTarget(target); + command.setWorkingDirectory(workingDirectory); + command.setResultBuilder(listener); + command.put(parameters); + + CommandRuntime runtime = new CommandRuntime(vcs, new IdeaSvnkitBasedAuthenticationCallback(vcs)); + return runtime.runWithAuthenticationAttempt(command); + } + protected static void callHandler(@Nullable ISVNEventHandler handler, @NotNull SVNEvent event) throws VcsException { if (handler != null) { try { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java index 782d521dc5c0..03c28c04359f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java @@ -55,7 +55,7 @@ public class CmdBrowseClient extends BaseSvnClient implements BrowseClient { CommandUtil.put(parameters, depth); parameters.add("--xml"); - CommandExecutor command = CommandUtil.execute(myVcs, target, SvnCommandName.list, parameters, null); + CommandExecutor command = execute(myVcs, target, SvnCommandName.list, parameters, null); try { parseOutput(target.getURL(), command, handler); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/change/CmdChangeListClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/change/CmdChangeListClient.java index c88d5d00054a..2791ce87af12 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/change/CmdChangeListClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/change/CmdChangeListClient.java @@ -32,7 +32,7 @@ public class CmdChangeListClient extends BaseSvnClient implements ChangeListClie // for now parsing of the output is not required as command is executed only for one file // and will be either successful or exception will be thrown - CommandUtil.execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.changelist, parameters, null); + execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.changelist, parameters, null); } @Override @@ -45,6 +45,6 @@ public class CmdChangeListClient extends BaseSvnClient implements ChangeListClie // for now parsing of the output is not required as command is executed only for one file // and will be either successful or exception will be thrown - CommandUtil.execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.changelist, parameters, null); + execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.changelist, parameters, null); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java index 8b593a84ac12..b7c92a3ed126 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java @@ -89,7 +89,7 @@ public class CmdCheckinClient extends BaseSvnClient implements CheckinClient { IdeaCommitHandler handler = new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator()); CmdCheckinClient.CommandListener listener = new CommandListener(handler); listener.setBaseDirectory(CommandUtil.correctUpToExistingParent(paths[0])); - CommandUtil.execute(myVcs, SvnTarget.fromFile(paths[0]), SvnCommandName.ci, parameters, listener); + execute(myVcs, SvnTarget.fromFile(paths[0]), SvnCommandName.ci, parameters, listener); listener.throwExceptionIfOccurred(); long revision = validateRevisionNumber(listener.getCommittedRevision()); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java index ee13f1c0de28..74eeadbb2fa1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdImportClient.java @@ -42,7 +42,7 @@ public class CmdImportClient extends BaseSvnClient implements ImportClient { CmdCheckinClient.CommandListener listener = new CmdCheckinClient.CommandListener(handler); listener.setBaseDirectory(path); - CommandUtil.execute(myVcs, SvnTarget.fromURL(url), SvnCommandName.importFolder, parameters, listener); + execute(myVcs, SvnTarget.fromURL(url), SvnCommandName.importFolder, parameters, listener); return listener.getCommittedRevision(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java index 6e151e4a6ae8..b292e43b9c1b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdCheckoutClient.java @@ -61,7 +61,7 @@ public class CmdCheckoutClient extends BaseSvnClient implements CheckoutClient { @NotNull List parameters) throws VcsException { BaseUpdateCommandListener listener = new BaseUpdateCommandListener(destination, handler); - CommandUtil.execute(myVcs, source, SvnCommandName.checkout, parameters, listener); + execute(myVcs, source, SvnCommandName.checkout, parameters, listener); listener.throwWrappedIfException(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdExportClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdExportClient.java index 6bff70f5236d..1e4011378fb7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdExportClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkout/CmdExportClient.java @@ -46,7 +46,7 @@ public class CmdExportClient extends BaseSvnClient implements ExportClient { BaseUpdateCommandListener listener = new BaseUpdateCommandListener(to, handler); - CommandUtil.execute(myVcs, from, to, SvnCommandName.export, parameters, listener); + execute(myVcs, from, to, SvnCommandName.export, parameters, listener); listener.throwWrappedIfException(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/cleanup/CmdCleanupClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/cleanup/CmdCleanupClient.java index 41eed4ccacc5..6ee1763d4120 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/cleanup/CmdCleanupClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/cleanup/CmdCleanupClient.java @@ -24,6 +24,6 @@ public class CmdCleanupClient extends BaseSvnClient implements CleanupClient { List parameters = new ArrayList(); CommandUtil.put(parameters, path); - CommandUtil.execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.cleanup, parameters, null); + execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.cleanup, parameters, null); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java index 0b529a954415..bd223001e5a4 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java @@ -170,42 +170,6 @@ public class CommandUtil { return (T) unmarshaller.unmarshal(new StringReader(data.trim())); } - /** - * Utility method for running commands. - * // TODO: Should be replaced with non-static analogue. - * - * @param vcs - * @param target - * @param name - * @param parameters - * @param listener - * @throws VcsException - */ - public static CommandExecutor execute(@NotNull SvnVcs vcs, - @NotNull SvnTarget target, - @NotNull SvnCommandName name, - @NotNull List parameters, - @Nullable LineCommandListener listener) throws VcsException { - return execute(vcs, target, null, name, parameters, listener); - } - - public static CommandExecutor execute(@NotNull SvnVcs vcs, - @NotNull SvnTarget target, - @Nullable File workingDirectory, - @NotNull SvnCommandName name, - @NotNull List parameters, - @Nullable LineCommandListener listener) throws VcsException { - Command command = new Command(name); - - command.setTarget(target); - command.setWorkingDirectory(workingDirectory); - command.setResultBuilder(listener); - command.put(parameters); - - CommandRuntime runtime = new CommandRuntime(vcs, new IdeaSvnkitBasedAuthenticationCallback(vcs)); - return runtime.runWithAuthenticationAttempt(command); - } - @NotNull public static File getHomeDirectory() { return new File(PathManager.getHomePath()); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/CmdConflictClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/CmdConflictClient.java index 64ae7ffcf6b1..39a222dbeaf3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/CmdConflictClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/conflict/CmdConflictClient.java @@ -35,6 +35,6 @@ public class CmdConflictClient extends BaseSvnClient implements ConflictClient { // for now parsing of the output is not required as command is executed only for one file // and will be either successful or exception will be thrown - CommandUtil.execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.resolve, parameters, null); + execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.resolve, parameters, null); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/content/CmdContentClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/CmdContentClient.java index 17b195eb927e..2995cb40fcbb 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/content/CmdContentClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/content/CmdContentClient.java @@ -30,7 +30,7 @@ public class CmdContentClient extends BaseSvnClient implements ContentClient { CommandUtil.put(parameters, target.getPathOrUrlString(), pegRevision); CommandUtil.put(parameters, revision); - CommandExecutor command = CommandUtil.execute(myVcs, target, SvnCommandName.cat, parameters, null); + CommandExecutor command = execute(myVcs, target, SvnCommandName.cat, parameters, null); byte[] bytes = command.getBinaryOutput().toByteArray(); ContentRevisionCache.checkContentsSize(target.getPathOrUrlString(), bytes.length); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java index 952001c2801e..4860d989d2ff 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java @@ -36,8 +36,7 @@ public class CmdCopyMoveClient extends BaseSvnClient implements CopyMoveClient { // directory being renamed will be blocked by svn process File workingDirectory = isMove && !SystemInfo.isFileSystemCaseSensitive && FileUtil.filesEqual(src, dst) ? CommandUtil.getHomeDirectory() : null; - CommandUtil - .execute(myVcs, SvnTarget.fromFile(dst), workingDirectory, isMove ? SvnCommandName.move : SvnCommandName.copy, parameters, null); + execute(myVcs, SvnTarget.fromFile(dst), workingDirectory, isMove ? SvnCommandName.move : SvnCommandName.copy, parameters, null); } @Override @@ -68,7 +67,7 @@ public class CmdCopyMoveClient extends BaseSvnClient implements CopyMoveClient { if (source.isFile()) { listener.setBaseDirectory(source.getFile()); } - CommandUtil.execute(myVcs, source, SvnCommandName.copy, parameters, listener); + execute(myVcs, source, SvnCommandName.copy, parameters, listener); return listener.getCommittedRevision(); } @@ -89,7 +88,7 @@ public class CmdCopyMoveClient extends BaseSvnClient implements CopyMoveClient { File workingDirectory = CommandUtil.getHomeDirectory(); BaseUpdateCommandListener listener = new BaseUpdateCommandListener(workingDirectory, handler); - CommandUtil.execute(myVcs, source, workingDirectory, SvnCommandName.copy, parameters, listener); + execute(myVcs, source, workingDirectory, SvnCommandName.copy, parameters, listener); listener.throwWrappedIfException(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/CmdDeleteClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/CmdDeleteClient.java index b0d2eae487be..7ab885a55bbb 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/CmdDeleteClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/CmdDeleteClient.java @@ -32,7 +32,7 @@ public class CmdDeleteClient extends BaseSvnClient implements DeleteClient { File workingDirectory = CommandUtil.getHomeDirectory(); BaseUpdateCommandListener listener = new BaseUpdateCommandListener(workingDirectory, handler); - CommandUtil.execute(myVcs, SvnTarget.fromFile(path), workingDirectory, SvnCommandName.delete, parameters, listener); + execute(myVcs, SvnTarget.fromFile(path), workingDirectory, SvnCommandName.delete, parameters, listener); listener.throwWrappedIfException(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java index 78b0e07837d4..0ad8373a0805 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java @@ -64,7 +64,7 @@ public class CmdDiffClient extends BaseSvnClient implements DiffClient { parameters.add("--xml"); parameters.add("--summarize"); - CommandExecutor executor = CommandUtil.execute(myVcs, target1, SvnCommandName.diff, parameters, null); + CommandExecutor executor = execute(myVcs, target1, SvnCommandName.diff, parameters, null); return parseOutput(target1, target2, executor); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java index 567c21f694e6..3494b9ac9d28 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java @@ -44,7 +44,7 @@ public class CmdHistoryClient extends BaseSvnClient implements HistoryClient { prepareCommand(target, startRevision, endRevision, stopOnCopy, discoverChangedPaths, includeMergedRevisions, limit); try { - CommandExecutor command = CommandUtil.execute(myVcs, target, SvnCommandName.log, parameters, null); + CommandExecutor command = execute(myVcs, target, SvnCommandName.log, parameters, null); // TODO: handler should be called in parallel with command execution, but this will be in other thread // TODO: check if that is ok for current handler implementation parseOutput(command, handler); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java index fdd28902bb6a..86b3bcb0c584 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java @@ -110,7 +110,7 @@ public class CmdInfoClient extends BaseSvnClient implements InfoClient { }; try { - CommandExecutor command = CommandUtil.execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.info, parameters, listener); + CommandExecutor command = execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.info, parameters, listener); return command.getOutput(); } @@ -210,7 +210,7 @@ public class CmdInfoClient extends BaseSvnClient implements InfoClient { fillParameters(path, pegRevision, revision, depth, parameters); CommandExecutor command; try { - command = CommandUtil.execute(myVcs, SvnTarget.fromURL(url), SvnCommandName.info, parameters, null); + command = execute(myVcs, SvnTarget.fromURL(url), SvnCommandName.info, parameters, null); } catch (VcsException e) { throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/CmdMergeClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/CmdMergeClient.java index adba7fa2fa6c..63eb66d9b002 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/CmdMergeClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/CmdMergeClient.java @@ -105,7 +105,7 @@ public class CmdMergeClient extends BaseSvnClient implements MergeClient { private void run(File destination, ISVNEventHandler handler, List parameters) throws VcsException { BaseUpdateCommandListener listener = new BaseUpdateCommandListener(CommandUtil.correctUpToExistingParent(destination), handler); - CommandUtil.execute(myVcs, SvnTarget.fromFile(destination), SvnCommandName.merge, parameters, listener); + execute(myVcs, SvnTarget.fromFile(destination), SvnCommandName.merge, parameters, listener); listener.throwWrappedIfException(); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/lock/CmdLockClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/lock/CmdLockClient.java index ff6d3f611766..abc4b5b794c2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/lock/CmdLockClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/lock/CmdLockClient.java @@ -32,7 +32,7 @@ public class CmdLockClient extends BaseSvnClient implements LockClient { parameters.add("--message"); parameters.add(message); - CommandExecutor command = CommandUtil.execute(myVcs, SvnTarget.fromFile(file), SvnCommandName.lock, parameters, null); + CommandExecutor command = execute(myVcs, SvnTarget.fromFile(file), SvnCommandName.lock, parameters, null); handleCommandCompletion(command, file, SVNEventAction.LOCKED, SVNEventAction.LOCK_FAILED, handler); } @@ -40,7 +40,7 @@ public class CmdLockClient extends BaseSvnClient implements LockClient { public void unlock(@NotNull File file, boolean force, @Nullable ISVNEventHandler handler) throws VcsException { List parameters = prepareParameters(file, force); - CommandExecutor command = CommandUtil.execute(myVcs, SvnTarget.fromFile(file), SvnCommandName.unlock, parameters, null); + CommandExecutor command = execute(myVcs, SvnTarget.fromFile(file), SvnCommandName.unlock, parameters, null); handleCommandCompletion(command, file, SVNEventAction.UNLOCKED, SVNEventAction.UNLOCK_FAILED, handler); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java index ce6d2b219bca..f1a57b6aa5ce 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java @@ -52,7 +52,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { // is critical for some parts of merge logic parameters.add("--xml"); - CommandExecutor command = CommandUtil.execute(myVcs, target, SvnCommandName.propget, parameters, null); + CommandExecutor command = execute(myVcs, target, SvnCommandName.propget, parameters, null); return parseSingleProperty(target, command.getOutput()); } @@ -67,7 +67,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { parameters.add(property); fillListParameters(target, revision, depth, parameters, false); - CommandExecutor command = CommandUtil.execute(myVcs, target, SvnCommandName.propget, parameters, null); + CommandExecutor command = execute(myVcs, target, SvnCommandName.propget, parameters, null); parseOutput(target, command.getOutput(), handler); } @@ -79,7 +79,7 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { List parameters = new ArrayList(); fillListParameters(target, revision, depth, parameters, true); - CommandExecutor command = CommandUtil.execute(myVcs, target, SvnCommandName.proplist, parameters, null); + CommandExecutor command = execute(myVcs, target, SvnCommandName.proplist, parameters, null); parseOutput(target, command.getOutput(), handler); } @@ -160,9 +160,8 @@ public class CmdPropertyClient extends BaseSvnClient implements PropertyClient { // "svn propset svn:ignore *.java . --depth empty") tries to set ignore also on child files and fails with error like // "svn: E200009: Cannot set 'svn:ignore' on a file ('...File1.java')". So here we manually force home directory to be used. // NOTE: that setting other properties (not svn:ignore) does not cause such error. - CommandUtil - .execute(myVcs, target, CommandUtil.getHomeDirectory(), isDelete ? SvnCommandName.propdel : SvnCommandName.propset, parameters, - null); + execute(myVcs, target, CommandUtil.getHomeDirectory(), isDelete ? SvnCommandName.propdel : SvnCommandName.propset, parameters, + null); } private void fillListParameters(@NotNull SvnTarget target, diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java index 02992c9c591f..aef5ae942687 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java @@ -40,7 +40,7 @@ public class CmdRevertClient extends BaseSvnClient implements RevertClient { // TODO: check if that is ok for current handler implementation // TODO: add possibility to invoke "handler.checkCancelled" - process should be killed CommandExecutor command = - CommandUtil.execute(myVcs, SvnTarget.fromFile(paths[0]), CommandUtil.getHomeDirectory(), SvnCommandName.revert, parameters, null); + execute(myVcs, SvnTarget.fromFile(paths[0]), CommandUtil.getHomeDirectory(), SvnCommandName.revert, parameters, null); FileStatusResultParser parser = new FileStatusResultParser(CHANGED_PATH, handler, new RevertStatusConvertor()); parser.parse(command.getOutput()); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java index b463d2f6ba27..235f5d1ecddc 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/status/CmdStatusClient.java @@ -101,7 +101,7 @@ public class CmdStatusClient extends BaseSvnClient implements StatusClient { CommandExecutor command; try { - command = CommandUtil.execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.st, parameters, null); + command = execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.st, parameters, null); } catch (VcsException e) { throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdRelocateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdRelocateClient.java index d6b86c934773..df3d9baa3a8d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdRelocateClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdRelocateClient.java @@ -24,6 +24,6 @@ public class CmdRelocateClient extends BaseSvnClient implements RelocateClient { parameters.add(toPrefix); CommandUtil.put(parameters, copyRoot, false); - CommandUtil.execute(myVcs, SvnTarget.fromFile(copyRoot), SvnCommandName.relocate, parameters, null); + execute(myVcs, SvnTarget.fromFile(copyRoot), SvnCommandName.relocate, parameters, null); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java index 7ccc9a507c63..051be8945b3e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/CmdUpdateClient.java @@ -80,7 +80,7 @@ public class CmdUpdateClient extends SvnKitUpdateClient { final BaseUpdateCommandListener listener = createCommandListener(paths, updatedToRevision, base); try { - CommandUtil.execute(myVcs, SvnTarget.fromFile(base), command, parameters, listener); + execute(myVcs, SvnTarget.fromFile(base), command, parameters, listener); } catch (VcsException e) { throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e)); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/upgrade/CmdUpgradeClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/upgrade/CmdUpgradeClient.java index cb516eb4386f..3a4e6eb6ce92 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/upgrade/CmdUpgradeClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/upgrade/CmdUpgradeClient.java @@ -51,7 +51,7 @@ public class CmdUpgradeClient extends BaseSvnClient implements UpgradeClient { FileStatusResultParser parser = new FileStatusResultParser(CHANGED_PATH, handler, new UpgradeStatusConvertor()); UpgradeLineCommandListener listener = new UpgradeLineCommandListener(parser); - CommandUtil.execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.upgrade, parameters, listener); + execute(myVcs, SvnTarget.fromFile(path), SvnCommandName.upgrade, parameters, listener); listener.throwIfException(); } diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java index 13d8202ce642..76cc3c8ce9af 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCommandLineStabilityTest.java @@ -2,8 +2,8 @@ package org.jetbrains.idea.svn; import com.intellij.openapi.vcs.VcsException; import junit.framework.Assert; +import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.commandLine.CommandExecutor; -import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.jetbrains.idea.svn.commandLine.SvnCommandName; import org.junit.Test; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -36,7 +36,7 @@ public class SvnCommandLineStabilityTest extends Svn17TestCase { SvnVcs vcs = SvnVcs.getInstance(myProject); File workingDirectory = new File(myWorkingCopyDir.getPath()); CommandExecutor command = - CommandUtil.execute(vcs, SvnTarget.fromFile(workingDirectory), workingDirectory, SvnCommandName.info, parameters, null); + BaseSvnClient.execute(vcs, SvnTarget.fromFile(workingDirectory), workingDirectory, SvnCommandName.info, parameters, null); final String result = command.getOutput(); System.out.println(result); Assert.assertNotNull(result); From 7ec9633cbc14e598e8f11f48c74009a5302d8123 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 17:08:54 +0400 Subject: [PATCH 40/65] svn: Refactored SvnBindException - use MultiMap to track errors --- .../svn/commandLine/SvnBindException.java | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java index 1976a31e311d..a083f1fc1ba2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java @@ -18,16 +18,13 @@ package org.jetbrains.idea.svn.commandLine; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.VcsException; -import com.intellij.util.LineSeparator; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.hash.HashMap; +import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnUtil; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNException; -import java.util.Map; import java.util.regex.Matcher; /** @@ -43,7 +40,7 @@ public class SvnBindException extends VcsException { public static final int ERROR_BASE = 120000; public static final int CATEGORY_SIZE = 5000; - private Map errors = new HashMap(); + @NotNull private final MultiMap errors = MultiMap.create(); public SvnBindException(String message) { super(message); @@ -60,7 +57,7 @@ public class SvnBindException extends VcsException { SVNException e = (SVNException)throwable; int code = e.getErrorMessage().getErrorCode().getCode(); - put(code, e.getMessage()); + errors.putValue(code, e.getMessage()); } } @@ -91,18 +88,7 @@ public class SvnBindException extends VcsException { Matcher matcher = SvnUtil.ERROR_PATTERN.matcher(message); while (matcher.find()) { - put(Integer.valueOf(matcher.group(2)), matcher.group()); - } - } - - private void put(int code, @Nullable String message) { - if (errors.containsKey(code)) { - if (!StringUtil.isEmpty(message)) { - errors.put(code, errors.get(code) + LineSeparator.LF.getSeparatorString() + message); - } - } - else { - errors.put(code, message); + errors.putValue(Integer.valueOf(matcher.group(2)), matcher.group()); } } } From 0d4ccd0f74b379b9691d708f57efe25fd4f00332 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 17:23:03 +0400 Subject: [PATCH 41/65] svn: Added ability to track warnings to SvnBindException --- .../svn/commandLine/SvnBindException.java | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java index a083f1fc1ba2..80c1f4078f85 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java @@ -23,9 +23,11 @@ import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnUtil; import org.tmatesoft.svn.core.SVNErrorCode; +import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Created with IntelliJ IDEA. @@ -41,12 +43,14 @@ public class SvnBindException extends VcsException { public static final int CATEGORY_SIZE = 5000; @NotNull private final MultiMap errors = MultiMap.create(); + @NotNull private final MultiMap warnings = MultiMap.create(); public SvnBindException(String message) { super(message); if (!StringUtil.isEmpty(message)) { - parseErrors(message); + parse(message, SvnUtil.ERROR_PATTERN, errors); + parse(message, SvnUtil.WARNING_PATTERN, warnings); } } @@ -56,39 +60,42 @@ public class SvnBindException extends VcsException { if (throwable instanceof SVNException) { SVNException e = (SVNException)throwable; int code = e.getErrorMessage().getErrorCode().getCode(); + int type = e.getErrorMessage().getType(); - errors.putValue(code, e.getMessage()); + (type == SVNErrorMessage.TYPE_ERROR ? errors : warnings).putValue(code, e.getMessage()); } } - public boolean contains(int error) { - return errors.containsKey(error); + public boolean contains(int code) { + return errors.containsKey(code) || warnings.containsKey(code); } - public boolean contains(@NotNull SVNErrorCode error) { - return errors.containsKey(error.getCode()); + public boolean contains(@NotNull SVNErrorCode code) { + return contains(code.getCode()); } public boolean containsCategory(int category) { final int categoryCode = getCategoryCode(category); - - return ContainerUtil.exists(errors.keySet(), new Condition() { + Condition belongsToCategoryCondition = new Condition() { @Override public boolean value(Integer code) { return getCategoryCode(code) == categoryCode; } - }); + }; + + return ContainerUtil.exists(errors.keySet(), belongsToCategoryCondition) || + ContainerUtil.exists(warnings.keySet(), belongsToCategoryCondition); } private static int getCategoryCode(int category) { return (category - ERROR_BASE) / CATEGORY_SIZE; } - private void parseErrors(@NotNull String message) { - Matcher matcher = SvnUtil.ERROR_PATTERN.matcher(message); + private static void parse(@NotNull String message, @NotNull Pattern pattern, @NotNull MultiMap map) { + Matcher matcher = pattern.matcher(message); while (matcher.find()) { - errors.putValue(Integer.valueOf(matcher.group(2)), matcher.group()); + map.putValue(Integer.valueOf(matcher.group(2)), matcher.group()); } } } From 7456ac5740faec32a5b7c2fe639d6e76695da322 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 18:32:15 +0400 Subject: [PATCH 42/65] svn: Use RA_ILLEGAL_URL error code for SVNException in command line info client when passed target does not exist (so CreateBranchOrTagAction.dirExists() works correctly for command line) --- .../src/org/jetbrains/idea/svn/api/BaseSvnClient.java | 4 ++-- .../src/org/jetbrains/idea/svn/info/CmdInfoClient.java | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java index 9403c4602bfe..b788d3074ec2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java @@ -88,7 +88,7 @@ public abstract class BaseSvnClient implements SvnClient { @NotNull SvnTarget target, @NotNull SvnCommandName name, @NotNull List parameters, - @Nullable LineCommandListener listener) throws VcsException { + @Nullable LineCommandListener listener) throws SvnBindException { return execute(vcs, target, null, name, parameters, listener); } @@ -97,7 +97,7 @@ public abstract class BaseSvnClient implements SvnClient { @Nullable File workingDirectory, @NotNull SvnCommandName name, @NotNull List parameters, - @Nullable LineCommandListener listener) throws VcsException { + @Nullable LineCommandListener listener) throws SvnBindException { Command command = new Command(name); command.setTarget(target); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java index 86b3bcb0c584..475dd1a4f77d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/info/CmdInfoClient.java @@ -28,7 +28,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.commandLine.*; -import org.jetbrains.idea.svn.commandLine.SvnExceptionWrapper; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.ISVNInfoHandler; import org.tmatesoft.svn.core.wc.SVNInfo; @@ -212,8 +211,10 @@ public class CmdInfoClient extends BaseSvnClient implements InfoClient { try { command = execute(myVcs, SvnTarget.fromURL(url), SvnCommandName.info, parameters, null); } - catch (VcsException e) { - throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e), e); + catch (SvnBindException e) { + SVNErrorCode code = e.contains(SVNErrorCode.RA_ILLEGAL_URL) ? SVNErrorCode.RA_ILLEGAL_URL : SVNErrorCode.IO_ERROR; + + throw new SVNException(SVNErrorMessage.create(code, e), e); } parseResult(handler, null, command.getOutput()); From e851587bd3e3808da965d8d8e32623a3b2d765b2 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Fri, 25 Apr 2014 18:42:58 +0400 Subject: [PATCH 43/65] svn: Refactored CreateBranchOrTagAction - do not create non-existent folders manually (as "svn copy" supports corresponding "--parents" option) --- .../svn/actions/CreateBranchOrTagAction.java | 35 ++++--------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java index c0b06f838293..e0ed9e06896d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java @@ -35,20 +35,18 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnStatusUtil; import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.checkin.IdeaCommitHandler; import org.jetbrains.idea.svn.checkin.CommitEventHandler; +import org.jetbrains.idea.svn.checkin.IdeaCommitHandler; import org.jetbrains.idea.svn.dialogs.CreateBranchOrTagDialog; import org.jetbrains.idea.svn.update.AutoSvnUpdater; import org.jetbrains.idea.svn.update.SingleRootSwitcher; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; -import java.util.ArrayList; -import java.util.List; public class CreateBranchOrTagAction extends BasicAction { protected String getActionName(AbstractVcs vcs) { @@ -96,7 +94,6 @@ public class CreateBranchOrTagAction extends BasicAction { return; } } - } catch (SVNException e) { throw new VcsException(e); @@ -111,7 +108,6 @@ public class CreateBranchOrTagAction extends BasicAction { progress.setText(SvnBundle.message("progress.text.copy.to", dstURL)); handler = new IdeaCommitHandler(progress); } - checkCreateDir(parentUrl, activeVcs, comment); SvnTarget source = isSrcFile ? SvnTarget.fromFile(srcFile, revision) : SvnTarget.fromURL(srcUrl, revision); long newRevision = activeVcs.getFactory(source).createCopyMoveClient() @@ -124,7 +120,8 @@ public class CreateBranchOrTagAction extends BasicAction { } } }; - ProgressManager.getInstance().runProcessWithProgressSynchronously(copyCommand, SvnBundle.message("progress.title.copy"), false, project); + ProgressManager.getInstance() + .runProcessWithProgressSynchronously(copyCommand, SvnBundle.message("progress.title.copy"), false, project); if (!exception.isNull()) { throw new VcsException(exception.get()); } @@ -148,24 +145,6 @@ public class CreateBranchOrTagAction extends BasicAction { } } - private static void checkCreateDir(@NotNull SVNURL url, @NotNull final SvnVcs activeVcs, @NotNull final String comment) - throws SVNException, VcsException { - final SVNURL baseUrl = url; - List dirsToCreate = new ArrayList(); - while(!dirExists(activeVcs, activeVcs.getProject(), url)) { - dirsToCreate.add(0, url); - url = url.removePathTail(); - if (url.getPath().length() == 0) { - throw new VcsException("Invalid repository root path for " + baseUrl); - } - } - if (! dirsToCreate.isEmpty()) { - // TODO: Works for 1.8 - implement this for command line - SVNCommitClient commitClient = activeVcs.createCommitClient(); - commitClient.doMkDir(dirsToCreate.toArray(new SVNURL[dirsToCreate.size()]), comment); - } - } - private static boolean dirExists(@NotNull final SvnVcs vcs, @NotNull Project project, @NotNull final SVNURL url) throws SVNException { final Ref excRef = new Ref(); final Ref resultRef = new Ref(Boolean.TRUE); @@ -190,10 +169,11 @@ public class CreateBranchOrTagAction extends BasicAction { final Application application = ApplicationManager.getApplication(); if (application.isDispatchThread()) { ProgressManager.getInstance().runProcessWithProgressSynchronously(taskImpl, "Checking target folder", true, project); - } else { + } + else { taskImpl.run(); } - if (! excRef.isNull()) throw excRef.get(); + if (!excRef.isNull()) throw excRef.get(); return resultRef.get(); } @@ -204,5 +184,4 @@ public class CreateBranchOrTagAction extends BasicAction { protected boolean isBatchAction() { return false; } - } From 673351fbf9bf1971a29b9b721aab389c9800b60c Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 28 Apr 2014 18:11:38 +0400 Subject: [PATCH 44/65] svn: Implemented ability to create folders directly in repository (for BrowseClient) --- .../idea/svn/browse/BrowseClient.java | 2 ++ .../idea/svn/browse/CmdBrowseClient.java | 20 +++++++++++++++++++ .../idea/svn/browse/SvnKitBrowseClient.java | 14 +++++++++++++ .../idea/svn/commandLine/SvnCommandName.java | 4 +++- 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/BrowseClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/BrowseClient.java index ea59a9a80dbf..92e64bb5230e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/BrowseClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/BrowseClient.java @@ -31,4 +31,6 @@ public interface BrowseClient extends SvnClient { void list(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable SVNDepth depth, @Nullable ISVNDirEntryHandler handler) throws VcsException; + + long createDirectory(@NotNull SvnTarget target, @NotNull String message, boolean makeParents) throws VcsException; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java index 03c28c04359f..20d60a9e50bf 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java @@ -17,9 +17,11 @@ package org.jetbrains.idea.svn.browse; import com.intellij.openapi.vcs.VcsException; import com.intellij.util.PathUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.jetbrains.idea.svn.checkin.CmdCheckinClient; import org.jetbrains.idea.svn.commandLine.CommandExecutor; import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.jetbrains.idea.svn.commandLine.SvnBindException; @@ -65,6 +67,24 @@ public class CmdBrowseClient extends BaseSvnClient implements BrowseClient { } } + @Override + public long createDirectory(@NotNull SvnTarget target, @NotNull String message, boolean makeParents) throws VcsException { + assertUrl(target); + + List parameters = ContainerUtil.newArrayList(); + + CommandUtil.put(parameters, target); + CommandUtil.put(parameters, makeParents, "--parents"); + parameters.add("--message"); + parameters.add(message); + + CmdCheckinClient.CommandListener listener = new CmdCheckinClient.CommandListener(null); + + execute(myVcs, target, SvnCommandName.mkdir, parameters, listener); + + return listener.getCommittedRevision(); + } + private static void parseOutput(@NotNull SVNURL url, @NotNull CommandExecutor command, @Nullable ISVNDirEntryHandler handler) throws VcsException, SVNException { try { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/SvnKitBrowseClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/SvnKitBrowseClient.java index 95388a12a8ec..aed0c1de14ab 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/SvnKitBrowseClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/SvnKitBrowseClient.java @@ -53,6 +53,20 @@ public class SvnKitBrowseClient extends BaseSvnClient implements BrowseClient { } } + @Override + public long createDirectory(@NotNull SvnTarget target, @NotNull String message, boolean makeParents) throws VcsException { + assertUrl(target); + + try { + SVNCommitInfo commitInfo = myVcs.createCommitClient().doMkDir(new SVNURL[]{target.getURL()}, message, null, makeParents); + + return commitInfo.getNewRevision(); + } + catch (SVNException e) { + throw new SvnBindException(e); + } + } + @Nullable private static ISVNDirEntryHandler wrapHandler(@Nullable ISVNDirEntryHandler handler) { return handler == null ? null : new SkipEmptyNameDirectoriesHandler(handler); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java index c31ce2355276..5bf58891c34d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java @@ -52,7 +52,9 @@ public enum SvnCommandName { export("export", false), upgrade("upgrade", true), list("list", false), - diff("diff", false); + diff("diff", false), + // currently used to create only folders directly in repository - so writable = false + mkdir("mkdir", false); private final String myName; private final boolean myWriteable; From 924f108eb5500846dd5272a64ecb325b7abf1757 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 28 Apr 2014 18:12:46 +0400 Subject: [PATCH 45/65] svn: Refactored ShareProjectAction - use common client factory model (instead of direct SVNCommitClient usage) --- .../idea/svn/actions/ShareProjectAction.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java index 0a81b08d6858..7c715a3971f7 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java @@ -37,7 +37,6 @@ import org.jetbrains.idea.svn.*; import org.jetbrains.idea.svn.api.ClientFactory; import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider; import org.jetbrains.idea.svn.dialogs.ShareDialog; -import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; @@ -220,10 +219,10 @@ public class ShareProjectAction extends BasicAction { return folderEmpty[0]; } - private static Pair createRemoteFolder(final SvnVcs vcs, - final SVNURL parent, + private static Pair createRemoteFolder(@NotNull final SvnVcs vcs, + @NotNull final SVNURL parent, final String folderName, - String commitText) throws SVNException { + String commitText) throws VcsException, SVNException { SVNURL url = parent.appendPath(folderName, false); final String urlText = url.toString(); final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); @@ -231,11 +230,13 @@ public class ShareProjectAction extends BasicAction { indicator.checkCanceled(); indicator.setText(SvnBundle.message("share.directory.create.dir.progress.text", urlText)); } - // TODO: Implement with command line client - final SVNCommitInfo info = - vcs.createCommitClient().doMkDir(new SVNURL[]{url}, SvnBundle.message("share.directory.commit.message", folderName, - ApplicationNamesInfo.getInstance().getFullProductName(), commitText)); - return new Pair(SVNRevision.create(info.getNewRevision()), url); + + String message = + SvnBundle.message("share.directory.commit.message", folderName, ApplicationNamesInfo.getInstance().getFullProductName(), commitText); + SvnTarget target = SvnTarget.fromURL(url); + long revision = vcs.getFactoryFromSettings().createBrowseClient().createDirectory(target, message, false); + + return Pair.create(SVNRevision.create(revision), url); } @Override From d19a90230e9d6c94a9705169413ce3e7b511d09f Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 28 Apr 2014 18:22:08 +0400 Subject: [PATCH 46/65] svn: Removed unused classes --- .../jetbrains/idea/svn/IgnoredFileInfo.java | 110 ------------------ .../org/jetbrains/idea/svn/RootMixedInfo.java | 55 --------- .../svn/SvnProxyAuthenticationNotifier.java | 46 -------- .../idea/svn/update/SvnUpdateGroups.java | 21 ---- 4 files changed, 232 deletions(-) delete mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/IgnoredFileInfo.java delete mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/RootMixedInfo.java delete mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/SvnProxyAuthenticationNotifier.java delete mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateGroups.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/IgnoredFileInfo.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/IgnoredFileInfo.java deleted file mode 100644 index 32432959e7d2..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/IgnoredFileInfo.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.svn; - -import com.intellij.openapi.diagnostic.Logger; -import org.tmatesoft.svn.core.SVNDepth; -import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions; -import org.tmatesoft.svn.core.wc.ISVNStatusHandler; -import org.tmatesoft.svn.core.wc.SVNRevision; -import org.tmatesoft.svn.core.wc.SVNStatus; -import org.tmatesoft.svn.core.wc.SVNStatusType; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class IgnoredFileInfo { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.IgnoredFileInfo"); - - // directory for which properties are collected - private final File myFile; - private final List myPatterns; - private final Set myFileNames; - private final Set myOldPatterns; - - public IgnoredFileInfo(final File file, final Set oldPatterns) { - myFile = file; - myPatterns = new ArrayList(); - myFileNames = new HashSet(); - myOldPatterns = oldPatterns; - } - - public void addFileName(final String name) { - myFileNames.add(name); - } - - public void addPattern(final String value) { - myPatterns.add(value); - } - - public void calculatePatterns(final SvnVcs vcs) { - final List names = new ArrayList(); - try { - vcs.createStatusClient().doStatus(myFile, SVNRevision.WORKING, SVNDepth.IMMEDIATES, false, true, true, false, new ISVNStatusHandler() { - public void handleStatus(SVNStatus status) throws SVNException { - if (SvnVcs.svnStatusIs(status, SVNStatusType.STATUS_IGNORED)) { - final String name = status.getFile().getName(); - if (! myFileNames.contains(name)) { - names.add(name); - } - } - } - }, null); - } - catch (SVNException e) { - LOG.info(e); - } - - for (String pattern : myOldPatterns) { - boolean usedSomewhereElse = false; - for (String name : names) { - if (DefaultSVNOptions.matches(pattern, name)) { - usedSomewhereElse = true; - break; - } - } - - if (! usedSomewhereElse) { - for (String name : myFileNames) { - if (DefaultSVNOptions.matches(pattern, name)) { - myPatterns.add(pattern); - break; - } - } - } - } - } - - public File getFile() { - return myFile; - } - - public List getPatterns() { - return myPatterns; - } - - public Set getFileNames() { - return myFileNames; - } - - public Set getOldPatterns() { - return myOldPatterns; - } -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootMixedInfo.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/RootMixedInfo.java deleted file mode 100644 index 3d0784687abf..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootMixedInfo.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.svn; - -import com.intellij.openapi.vfs.VirtualFile; -import org.tmatesoft.svn.core.SVNURL; - -public class RootMixedInfo { - /** - * working copy root path - */ - private final String myFilePath; - private final VirtualFile myFile; - /** - * url corresponding to working copy root - */ - private final SVNURL myUrl; - private final VirtualFile myParentVcsRoot; - - public RootMixedInfo(final String filePath, final VirtualFile file, final SVNURL url, final VirtualFile parentVcsRoot) { - myFilePath = filePath; - myFile = file; - myUrl = url; - myParentVcsRoot = parentVcsRoot; - } - - public String getFilePath() { - return myFilePath; - } - - public VirtualFile getFile() { - return myFile; - } - - public SVNURL getUrl() { - return myUrl; - } - - public VirtualFile getParentVcsRoot() { - return myParentVcsRoot; - } -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnProxyAuthenticationNotifier.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnProxyAuthenticationNotifier.java deleted file mode 100644 index e949b4aae8f7..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnProxyAuthenticationNotifier.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.svn; - -import com.intellij.notification.NotificationType; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.impl.GenericNotifierImpl; -import org.jetbrains.annotations.NotNull; - -// todo be done -// todo : two kinds. positive: either into common proxy, or into system properties -public class SvnProxyAuthenticationNotifier extends GenericNotifierImpl { - public SvnProxyAuthenticationNotifier(Project project, @NotNull String groupId, @NotNull String title, @NotNull NotificationType type) { - super(project, groupId, title, type); - } - - @Override - protected boolean ask(String obj, String description) { - return false; //To change body of implemented methods use File | Settings | File Templates. - } - - @NotNull - @Override - protected String getKey(String obj) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - @NotNull - @Override - protected String getNotificationContent(String obj) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } -} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateGroups.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateGroups.java deleted file mode 100644 index 92b92fdb7b25..000000000000 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateGroups.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.idea.svn.update; - -public interface SvnUpdateGroups { -// String MERGED_WITH_PROPERTY_CONFLICT = "MERGED_WITH_PROPERTY_CONFLICT"; - String MERGED_WITH_TREE_CONFLICT = "MERGED_WITH_TREE_CONFLICT"; -} From f41cb93faf4c137fe63abe5f009b51151a6e0776 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 28 Apr 2014 19:11:55 +0400 Subject: [PATCH 47/65] svn: Refactored CreateBranchOrTagAction - removed unnecessary parameters, removed todo items --- .../idea/svn/actions/CreateBranchOrTagAction.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java index e0ed9e06896d..a4cd74277876 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java @@ -87,7 +87,7 @@ public class CreateBranchOrTagAction extends BasicAction { dstSvnUrl = SVNURL.parseURIEncoded(dstURL); parentUrl = dstSvnUrl.removePathTail(); - if (!dirExists(activeVcs, project, parentUrl)) { + if (!dirExists(activeVcs, parentUrl)) { int rc = Messages.showYesNoDialog(project, "The repository path '" + parentUrl + "' does not exist. Would you like to create it?", "Branch or Tag", Messages.getQuestionIcon()); if (rc == Messages.NO) { @@ -145,7 +145,7 @@ public class CreateBranchOrTagAction extends BasicAction { } } - private static boolean dirExists(@NotNull final SvnVcs vcs, @NotNull Project project, @NotNull final SVNURL url) throws SVNException { + private static boolean dirExists(@NotNull final SvnVcs vcs, @NotNull final SVNURL url) throws SVNException { final Ref excRef = new Ref(); final Ref resultRef = new Ref(Boolean.TRUE); @@ -155,7 +155,6 @@ public class CreateBranchOrTagAction extends BasicAction { vcs.getInfo(url, SVNRevision.HEAD); } catch (SVNException e) { - // TODO: Check what error code returned by cmd client and implement corresponding support if (e.getErrorMessage().getErrorCode().equals(SVNErrorCode.RA_ILLEGAL_URL)) { resultRef.set(Boolean.FALSE); } @@ -168,7 +167,7 @@ public class CreateBranchOrTagAction extends BasicAction { final Application application = ApplicationManager.getApplication(); if (application.isDispatchThread()) { - ProgressManager.getInstance().runProcessWithProgressSynchronously(taskImpl, "Checking target folder", true, project); + ProgressManager.getInstance().runProcessWithProgressSynchronously(taskImpl, "Checking target folder", true, vcs.getProject()); } else { taskImpl.run(); From 55614bba8e3f5b0dafbb45b26e1f3438d727197a Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 28 Apr 2014 19:29:08 +0400 Subject: [PATCH 48/65] svn: Refactored RepositoryBrowserDialog - make folder creation logic use common client factory model (instead of direct SVNCommitClient usage) --- .../svn/dialogs/RepositoryBrowserDialog.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java index 4a7aa2defdea..cc46ebd6a5b2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java @@ -34,6 +34,7 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.vcs.*; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangesUtil; @@ -70,6 +71,7 @@ import org.tmatesoft.svn.core.wc.SVNCommitClient; import org.tmatesoft.svn.core.wc.SVNCopyClient; import org.tmatesoft.svn.core.wc.SVNCopySource; import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc2.SvnTarget; import javax.swing.*; import javax.swing.tree.TreeNode; @@ -1001,7 +1003,7 @@ public class RepositoryBrowserDialog extends DialogWrapper { } protected static void doMkdir(final SVNURL url, final String comment, final Project project) { - final SVNException[] exception = new SVNException[1]; + final Ref exception = new Ref(); Runnable command = new Runnable() { public void run() { ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); @@ -1009,18 +1011,18 @@ public class RepositoryBrowserDialog extends DialogWrapper { progress.setText(SvnBundle.message("progress.text.browser.creating", url.toString())); } SvnVcs vcs = SvnVcs.getInstance(project); + SvnTarget target = SvnTarget.fromURL(url); try { - SVNCommitClient committer = vcs.createCommitClient(); - committer.doMkDir(new SVNURL[] {url}, comment); + vcs.getFactoryFromSettings().createBrowseClient().createDirectory(target, comment, false); } - catch (SVNException e) { - exception[0] = e; + catch (VcsException e) { + exception.set(e); } } }; ProgressManager.getInstance().runProcessWithProgressSynchronously(command, SvnBundle.message("progress.text.create.remote.folder"), false, project); - if (exception[0] != null) { - Messages.showErrorDialog(exception[0].getMessage(), SvnBundle.message("message.text.error")); + if (!exception.isNull()) { + Messages.showErrorDialog(exception.get().getMessage(), SvnBundle.message("message.text.error")); } } From 65fd69c8c039878a8876d54522dcb7923f7dfe89 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 28 Apr 2014 20:52:10 +0400 Subject: [PATCH 49/65] svn: Implemented ability to delete files/folders directly from repository (for DeleteClient) --- .../idea/svn/delete/CmdDeleteClient.java | 19 +++++++++++++++++++ .../idea/svn/delete/DeleteClient.java | 3 +++ .../idea/svn/delete/SvnKitDeleteClient.java | 15 +++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/CmdDeleteClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/CmdDeleteClient.java index 7ab885a55bbb..dfd6d72cc0f9 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/CmdDeleteClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/CmdDeleteClient.java @@ -1,12 +1,15 @@ package org.jetbrains.idea.svn.delete; import com.intellij.openapi.vcs.VcsException; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.jetbrains.idea.svn.checkin.CmdCheckinClient; import org.jetbrains.idea.svn.commandLine.BaseUpdateCommandListener; import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.jetbrains.idea.svn.commandLine.SvnCommandName; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -37,4 +40,20 @@ public class CmdDeleteClient extends BaseSvnClient implements DeleteClient { listener.throwWrappedIfException(); } } + + @Override + public long delete(@NotNull SVNURL url, @NotNull String message) throws VcsException { + SvnTarget target = SvnTarget.fromURL(url); + List parameters = ContainerUtil.newArrayList(); + + CommandUtil.put(parameters, target); + parameters.add("--message"); + parameters.add(message); + + CmdCheckinClient.CommandListener listener = new CmdCheckinClient.CommandListener(null); + + execute(myVcs, target, SvnCommandName.delete, parameters, listener); + + return listener.getCommittedRevision(); + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/DeleteClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/DeleteClient.java index 013696e2cf6c..ec6f01481d44 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/DeleteClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/DeleteClient.java @@ -4,6 +4,7 @@ import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.SvnClient; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import java.io.File; @@ -14,4 +15,6 @@ import java.io.File; public interface DeleteClient extends SvnClient { void delete(@NotNull File path, boolean force, boolean dryRun, @Nullable ISVNEventHandler handler) throws VcsException; + + long delete(@NotNull SVNURL url, @NotNull String message) throws VcsException; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/SvnKitDeleteClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/SvnKitDeleteClient.java index c433b970215d..940f36e7b731 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/SvnKitDeleteClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/delete/SvnKitDeleteClient.java @@ -4,7 +4,10 @@ import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; +import org.jetbrains.idea.svn.commandLine.SvnBindException; +import org.tmatesoft.svn.core.SVNCommitInfo; import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNWCClient; @@ -27,4 +30,16 @@ public class SvnKitDeleteClient extends BaseSvnClient implements DeleteClient { throw new VcsException(e); } } + + @Override + public long delete(@NotNull SVNURL url, @NotNull String message) throws VcsException { + try { + SVNCommitInfo commitInfo = myVcs.createCommitClient().doDelete(new SVNURL[]{url}, message); + + return commitInfo.getNewRevision(); + } + catch (SVNException e) { + throw new SvnBindException(e); + } + } } From 58734a2d6a7be834d0f09fe80033f9ee7666f914 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 28 Apr 2014 20:53:20 +0400 Subject: [PATCH 50/65] svn: Refactored RepositoryBrowserDialog - make file/folder deletion logic use common client factory model (instead of direct SVNCommitClient usage) --- .../svn/dialogs/RepositoryBrowserDialog.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java index cc46ebd6a5b2..7c12954b49da 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java @@ -67,7 +67,6 @@ import org.tmatesoft.svn.core.io.ISVNEditor; import org.tmatesoft.svn.core.io.ISVNReporter; import org.tmatesoft.svn.core.io.ISVNReporterBaton; import org.tmatesoft.svn.core.io.SVNRepository; -import org.tmatesoft.svn.core.wc.SVNCommitClient; import org.tmatesoft.svn.core.wc.SVNCopyClient; import org.tmatesoft.svn.core.wc.SVNCopySource; import org.tmatesoft.svn.core.wc.SVNRevision; @@ -809,7 +808,7 @@ public class RepositoryBrowserDialog extends DialogWrapper { } } private boolean doDelete(final SVNURL url, final String comment) { - final SVNException[] exception = new SVNException[1]; + final Ref exception = new Ref(); final Project project = myBrowserComponent.getProject(); Runnable command = new Runnable() { public void run() { @@ -819,19 +818,18 @@ public class RepositoryBrowserDialog extends DialogWrapper { } SvnVcs vcs = SvnVcs.getInstance(project); try { - SVNCommitClient committer = vcs.createCommitClient(); - committer.doDelete(new SVNURL[]{url}, comment); + vcs.getFactoryFromSettings().createDeleteClient().delete(url, comment); } - catch (SVNException e) { - exception[0] = e; + catch (VcsException e) { + exception.set(e); } } }; ProgressManager.getInstance().runProcessWithProgressSynchronously(command, SvnBundle.message("progress.title.browser.delete"), false, project); - if (exception[0] != null) { - Messages.showErrorDialog(exception[0].getMessage(), SvnBundle.message("message.text.error")); + if (!exception.isNull()) { + Messages.showErrorDialog(exception.get().getMessage(), SvnBundle.message("message.text.error")); } - return exception[0] == null; + return exception.isNull(); } } From 7a95352a99bfbaaba9cd6a31da22c19c403d3196 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 28 Apr 2014 22:46:10 +0400 Subject: [PATCH 51/65] svn: Implemented ability to move files/folders directly in repository (for CopyMoveClient) --- .../svn/actions/CreateBranchOrTagAction.java | 2 +- .../idea/svn/copy/CmdCopyMoveClient.java | 26 ++++++++++++------- .../idea/svn/copy/CopyMoveClient.java | 2 ++ .../idea/svn/copy/SvnKitCopyMoveClient.java | 4 ++- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java index a4cd74277876..7655751ded40 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java @@ -111,7 +111,7 @@ public class CreateBranchOrTagAction extends BasicAction { SvnTarget source = isSrcFile ? SvnTarget.fromFile(srcFile, revision) : SvnTarget.fromURL(srcUrl, revision); long newRevision = activeVcs.getFactory(source).createCopyMoveClient() - .copy(source, SvnTarget.fromURL(dstSvnUrl), revision, true, comment, handler); + .copy(source, SvnTarget.fromURL(dstSvnUrl), revision, true, false, comment, handler); updateStatusBar(newRevision, project); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java index 4860d989d2ff..e73e9fb4013f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CmdCopyMoveClient.java @@ -8,7 +8,9 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.checkin.CmdCheckinClient; import org.jetbrains.idea.svn.checkin.CommitEventHandler; -import org.jetbrains.idea.svn.commandLine.*; +import org.jetbrains.idea.svn.commandLine.BaseUpdateCommandListener; +import org.jetbrains.idea.svn.commandLine.CommandUtil; +import org.jetbrains.idea.svn.commandLine.SvnCommandName; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -36,21 +38,21 @@ public class CmdCopyMoveClient extends BaseSvnClient implements CopyMoveClient { // directory being renamed will be blocked by svn process File workingDirectory = isMove && !SystemInfo.isFileSystemCaseSensitive && FileUtil.filesEqual(src, dst) ? CommandUtil.getHomeDirectory() : null; - execute(myVcs, SvnTarget.fromFile(dst), workingDirectory, isMove ? SvnCommandName.move : SvnCommandName.copy, parameters, null); + execute(myVcs, SvnTarget.fromFile(dst), workingDirectory, getCommandName(isMove), parameters, null); } @Override public long copy(@NotNull SvnTarget source, - @NotNull SvnTarget destination, - @Nullable SVNRevision revision, - boolean makeParents, - @NotNull String message, - @Nullable CommitEventHandler handler) throws VcsException { + @NotNull SvnTarget destination, + @Nullable SVNRevision revision, + boolean makeParents, + boolean isMove, + @NotNull String message, + @Nullable CommitEventHandler handler) throws VcsException { if (!destination.isURL()) { throw new IllegalArgumentException("Only urls are supported as destination " + destination); } - // TODO: Check that command fails when destination exists List parameters = new ArrayList(); CommandUtil.put(parameters, source); @@ -63,11 +65,10 @@ public class CmdCopyMoveClient extends BaseSvnClient implements CopyMoveClient { // copy to url output is the same as commit output - just statuses have "copy of" suffix // so "Adding" will be "Adding copy of" CmdCheckinClient.CommandListener listener = new CmdCheckinClient.CommandListener(handler); - // TODO: Check correctness when source is url if (source.isFile()) { listener.setBaseDirectory(source.getFile()); } - execute(myVcs, source, SvnCommandName.copy, parameters, listener); + execute(myVcs, source, getCommandName(isMove), parameters, listener); return listener.getCommittedRevision(); } @@ -92,4 +93,9 @@ public class CmdCopyMoveClient extends BaseSvnClient implements CopyMoveClient { listener.throwWrappedIfException(); } + + @NotNull + private static SvnCommandName getCommandName(boolean isMove) { + return isMove ? SvnCommandName.move : SvnCommandName.copy; + } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CopyMoveClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CopyMoveClient.java index 8fb3cf4af573..dd4395f612b6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CopyMoveClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/CopyMoveClient.java @@ -23,6 +23,7 @@ public interface CopyMoveClient extends SvnClient { * @param destination * @param revision * @param makeParents + * @param isMove * @param message * @param handler * @return new revision number @@ -32,6 +33,7 @@ public interface CopyMoveClient extends SvnClient { @NotNull SvnTarget destination, @Nullable SVNRevision revision, boolean makeParents, + boolean isMove, @NotNull String message, @Nullable CommitEventHandler handler) throws VcsException; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java index 6a600a1fcc55..0888a546e892 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/copy/SvnKitCopyMoveClient.java @@ -40,6 +40,7 @@ public class SvnKitCopyMoveClient extends BaseSvnClient implements CopyMoveClien @NotNull SvnTarget destination, @Nullable SVNRevision revision, boolean makeParents, + boolean isMove, @NotNull String message, @Nullable CommitEventHandler handler) throws VcsException { @@ -53,7 +54,8 @@ public class SvnKitCopyMoveClient extends BaseSvnClient implements CopyMoveClien SVNCommitInfo info; try { - info = client.doCopy(new SVNCopySource[]{copySource}, destination.getURL(), false, makeParents, true, message, null); + info = client + .doCopy(new SVNCopySource[]{copySource}, destination.getURL(), isMove, makeParents, true, message, null); } catch (SVNException e) { throw new VcsException(e); From 9fa19ab13729623e32d638b5167558c6b2a0d913 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Mon, 28 Apr 2014 22:48:08 +0400 Subject: [PATCH 52/65] svn: Refactored RepositoryBrowserDialog - make "move file/folder" logic use common client factory model (instead of direct SVNCopyClient usage) --- .../svn/dialogs/RepositoryBrowserDialog.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java index 7c12954b49da..9ff0be4c50b0 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java @@ -67,8 +67,6 @@ import org.tmatesoft.svn.core.io.ISVNEditor; import org.tmatesoft.svn.core.io.ISVNReporter; import org.tmatesoft.svn.core.io.ISVNReporterBaton; import org.tmatesoft.svn.core.io.SVNRepository; -import org.tmatesoft.svn.core.wc.SVNCopyClient; -import org.tmatesoft.svn.core.wc.SVNCopySource; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.SvnTarget; @@ -1025,7 +1023,7 @@ public class RepositoryBrowserDialog extends DialogWrapper { } private void doCopy(final SVNURL src, final SVNURL dst, final boolean move, final String comment) { - final SVNException[] exception = new SVNException[1]; + final Ref exception = new Ref(); Runnable command = new Runnable() { public void run() { ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); @@ -1035,19 +1033,18 @@ public class RepositoryBrowserDialog extends DialogWrapper { } SvnVcs vcs = SvnVcs.getInstance(myProject); try { - SVNCopyClient committer = vcs.createCopyClient(); - final SVNCopySource[] copySource = new SVNCopySource[] {new SVNCopySource(SVNRevision.HEAD, SVNRevision.HEAD, src)}; - committer.doCopy(copySource, dst, move, true, true, comment, null); + vcs.getFactoryFromSettings().createCopyMoveClient().copy(SvnTarget.fromURL(src), SvnTarget.fromURL(dst), SVNRevision.HEAD, true, + move, comment, null); } - catch (SVNException e) { - exception[0] = e; + catch (VcsException e) { + exception.set(e); } } }; String progressTitle = move ? SvnBundle.message("progress.title.browser.move") : SvnBundle.message("progress.title.browser.copy"); ProgressManager.getInstance().runProcessWithProgressSynchronously(command, progressTitle, false, myProject); - if (exception[0] != null) { - Messages.showErrorDialog(exception[0].getMessage(), SvnBundle.message("message.text.error")); + if (!exception.isNull()) { + Messages.showErrorDialog(exception.get().getMessage(), SvnBundle.message("message.text.error")); } } From ca2c75e355295ffba6c8ed0cd6e122b7defec8af Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 29 Apr 2014 15:20:06 +0400 Subject: [PATCH 53/65] svn: Refactored RepositoryBrowserDialog - removed unused and commented code --- .../svn/dialogs/RepositoryBrowserDialog.java | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java index 9ff0be4c50b0..a6da5c5f7cb3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java @@ -87,9 +87,6 @@ public class RepositoryBrowserDialog extends DialogWrapper { protected final SvnVcs myVCS; private RepositoryBrowserComponent myRepositoryBrowser; - @NonNls public static final String COPY_OF_PREFIX = "CopyOf"; - @NonNls public static final String NEW_FOLDER_POSTFIX = "NewFolder"; - private final DeleteAction myDeleteAction; private AnAction copyUrlAction; private AnAction mkDirAction; @@ -1181,16 +1178,6 @@ public class RepositoryBrowserDialog extends DialogWrapper { return; } final Collection changesList = changes.values(); - /*final Collection changesListConverted = new ArrayList(changesList.size()); - for (Change change : changesList) { - final FilePath path = ChangesUtil.getFilePath(change); - final Change newChange = new Change( - new UrlContentRevision(change.getBeforeRevision(), - FilePathImpl.createNonLocal(SVNPathUtil.append(sourceUrl.toString(), path.getName()), path.isDirectory()), revision), - new UrlContentRevision(change.getAfterRevision(), - FilePathImpl.createNonLocal(SVNPathUtil.append(targetUrl.toString(), path.getName()), path.isDirectory()), revision)); - changesListConverted.add(newChange); - }*/ final String title = SvnBundle.message("repository.browser.compare.title", sourceTitle, targetTitle); SwingUtilities.invokeLater(new Runnable() { @@ -1228,10 +1215,6 @@ public class RepositoryBrowserDialog extends DialogWrapper { } } - public void setDefaultExpander(final NotNullFunction expanderFactory) { - myRepositoryBrowser.setLazyLoadingExpander(expanderFactory); - } - private static class UrlContentRevision implements ContentRevision { private final ContentRevision myContentRevision; private final FilePath myPath; From 47d8b3d493b82cc3ff4363ce512beb72bf2bf4f1 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 29 Apr 2014 17:15:37 +0400 Subject: [PATCH 54/65] svn: Refactored MergeFromTheirsResolver - use common client factory model (instead of direct SVNWCClient usage) --- .../src/org/jetbrains/idea/svn/add/SvnKitAddClient.java | 4 ++++ .../idea/svn/treeConflict/MergeFromTheirsResolver.java | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/add/SvnKitAddClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/add/SvnKitAddClient.java index d6250c71f073..2c397c73fa67 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/add/SvnKitAddClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/add/SvnKitAddClient.java @@ -16,6 +16,10 @@ import java.io.File; */ public class SvnKitAddClient extends BaseSvnClient implements AddClient { + /** + * TODO: Implement correct support for includeIgnored parameter. Also check that correct depth will be used for all cases (when another + * TODO: overload of doAdd() is used) as, for instance, SVNDepth.recurseFromDepth(EMPTY) = false, SVNDepth.fromRecursive(false) = FILES. + */ @Override public void add(@NotNull File file, @Nullable SVNDepth depth, diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java index 31b040cd98dd..b6dd8afed944 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java @@ -53,7 +53,6 @@ import org.jetbrains.idea.svn.*; import org.jetbrains.idea.svn.history.SvnChangeList; import org.jetbrains.idea.svn.history.SvnRepositoryLocation; import org.tmatesoft.svn.core.SVNDepth; -import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNNodeKind; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNTreeConflictDescription; @@ -285,9 +284,13 @@ public class MergeFromTheirsResolver { @Override public void run(ContinuationContext context) { try { - myVcs.createWCClient().doAdd(myOldFilePath.getIOFile(), true, true, true, SVNDepth.EMPTY, false, true); + // TODO: Previously SVNKit client was invoked with mkDir=true option - so corresponding directory would be created. Now mkDir=false + // TODO: is used. Command line also does not support automatic directory creation. + // TODO: Need to check additionally if there are cases when directory does not exist and add corresponding code. + myVcs.getFactory(myOldFilePath.getIOFile()).createAddClient() + .add(myOldFilePath.getIOFile(), SVNDepth.EMPTY, true, false, true, null); } - catch (SVNException e) { + catch (VcsException e) { context.handleException(e, true); } } From 4f1e8e6424fff7a1e312405ce97c5b07cd376a0c Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 29 Apr 2014 20:29:06 +0400 Subject: [PATCH 55/65] svn: Refactored SvnAuthenticationManager - removed unused/commented code, code simplifications, warnings fixes --- .../idea/svn/SvnAuthenticationManager.java | 46 ++++++------------- ...IdeaSvnkitBasedAuthenticationCallback.java | 4 +- 2 files changed, 15 insertions(+), 35 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java index 06005731a860..626cf6241eea 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java @@ -25,10 +25,12 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.*; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Getter; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vcs.CalledInAwt; import com.intellij.openapi.vcs.changes.committed.AbstractCalledLater; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.util.EventDispatcher; @@ -563,7 +565,7 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im } } - public void acknowledgeForSSL(boolean accepted, String kind, String realm, SVNErrorMessage message, SVNAuthentication proxy) { + public void acknowledgeForSSL(boolean accepted, SVNAuthentication proxy) { if (accepted && proxy instanceof SVNSSLAuthentication && (((SVNSSLAuthentication) proxy).getCertificateFile() != null)) { final SVNSSLAuthentication svnsslAuthentication = (SVNSSLAuthentication)proxy; final SVNURL url = svnsslAuthentication.getURL(); @@ -572,13 +574,9 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im final SVNCompositeConfigFile serversFile = provider.getServersFile(); String groupName = getGroupName(serversFile.getProperties("groups"), url.getHost()); - if (StringUtil.isEmptyOrSpaces(groupName)) { - serversFile.setPropertyValue("global", SvnServerFileKeys.SSL_CLIENT_CERT_FILE, svnsslAuthentication.getCertificateFile().getPath(), true); - //serversFile.setPropertyValue("global", SvnServerFileKeys.SSL_CLIENT_CERT_PASSWORD, null, true); - } else { - serversFile.setPropertyValue(groupName, SvnServerFileKeys.SSL_CLIENT_CERT_FILE, svnsslAuthentication.getCertificateFile().getPath(), true); - //serversFile.setPropertyValue(groupName, SvnServerFileKeys.SSL_CLIENT_CERT_PASSWORD, null, true); - } + groupName = StringUtil.isEmptyOrSpaces(groupName) ? "global" : groupName; + serversFile + .setPropertyValue(groupName, SvnServerFileKeys.SSL_CLIENT_CERT_FILE, svnsslAuthentication.getCertificateFile().getPath(), true); serversFile.save(); } } @@ -597,7 +595,7 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im String host = url.getHost(); String proxyHost = getServersPropertyIdea(host, HTTP_PROXY_HOST); - if ((proxyHost == null) || "".equals(proxyHost.trim())) { + if (StringUtil.isEmptyOrSpaces(proxyHost)) { if (getConfig().isIsUseDefaultProxy()) { // ! use common proxy if it is set try { @@ -607,8 +605,8 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im if (HttpConfigurable.isRealProxy(proxy) && Proxy.Type.HTTP.equals(proxy.type())) { final SocketAddress address = proxy.address(); if (address instanceof InetSocketAddress) { - return new MyPromptingProxyManager(((InetSocketAddress)address).getHostName(), "" + ((InetSocketAddress)address).getPort(), - url.getProtocol()); + return new MyPromptingProxyManager(((InetSocketAddress)address).getHostName(), + String.valueOf(((InetSocketAddress)address).getPort()), url.getProtocol()); } } } @@ -642,7 +640,7 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im private static class MyPromptingProxyManager extends MySimpleProxyManager { - private static final String ourPrompt = "Proxy authentication"; + private final String myProtocol; private MyPromptingProxyManager(final String host, final String port, String protocol) { @@ -766,7 +764,7 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im return getPropertyIdea(host, serversFile, name); } - private String getPropertyIdea(String host, SVNCompositeConfigFile serversFile, final String name) { + private static String getPropertyIdea(String host, SVNCompositeConfigFile serversFile, final String name) { String groupName = getGroupName(serversFile.getProperties("groups"), host); if (groupName != null) { Map hostProps = serversFile.getProperties(groupName); @@ -837,7 +835,7 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im return value == null || "yes".equalsIgnoreCase(value) || "on".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value); } - private ModalityState getCurrent() { + private static ModalityState getCurrent() { if (ApplicationManager.getApplication().isDispatchThread()) { return ModalityState.current(); } @@ -848,18 +846,6 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im return pi.getModalityState(); } - /** - * Shows a yes/no question whether user wants to store his password in plain text and returns his answer. - * @param title title of the questioning dialog. - * @param message questioning message to be displayed. - * @return true if user agrees to store his password in plaintext, false if he doesn't. - */ - @CalledInAwt - private boolean askToStoreUnencrypted(String title, String message) { - final int answer = Messages.showYesNoDialog(myProject, message, title, Messages.getQuestionIcon()); - return answer == Messages.YES; - } - public void setInteraction(SvnAuthenticationInteraction interaction) { myInteraction = interaction; } @@ -914,10 +900,6 @@ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager im } } - private static boolean isLion() { - return SystemInfo.isMac && SystemInfo.isMacOSSnowLeopard && ! SystemInfo.OS_VERSION.startsWith("10.6"); - } - public class IdeaSVNHostOptionsProvider extends DefaultSVNHostOptionsProvider { public IdeaSVNHostOptionsProvider() { super(myConfigDirectory); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index 796e1795b360..1b1b8ecea36d 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -654,9 +654,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall private boolean acknowledgeSSL(SvnAuthenticationManager manager, SVNAuthentication svnAuthentication) throws SVNException { if (svnAuthentication instanceof SVNSSLAuthentication && (((SVNSSLAuthentication) svnAuthentication).getCertificateFile() != null)) { - manager.acknowledgeForSSL(true, getFromType(svnAuthentication), - ((SVNSSLAuthentication) svnAuthentication).getCertificateFile().getPath(), - null, svnAuthentication); + manager.acknowledgeForSSL(true, svnAuthentication); manager.acknowledgeAuthentication(true, getFromType(svnAuthentication), ((SVNSSLAuthentication) svnAuthentication).getCertificateFile().getPath(), null, svnAuthentication, svnAuthentication.getURL()); From dedc16a5615c321f2ff5a8c11646fae9e51ccf48 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 29 Apr 2014 22:02:51 +0400 Subject: [PATCH 56/65] svn: Refactored IdeaSvnkitBasedAuthenticationCallback - code simplifications, @NotNull --- ...IdeaSvnkitBasedAuthenticationCallback.java | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index 1b1b8ecea36d..14391ddd2a94 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -540,12 +540,14 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } } - private boolean storeCredentials(SvnAuthenticationManager manager, final SVNAuthentication authentication, final String realm) throws SVNException { + private static boolean storeCredentials(@NotNull SvnAuthenticationManager manager, final SVNAuthentication authentication, String realm) + throws SVNException { try { - final String kind = getFromType(authentication); - if (! acknowledgeSSL(manager, authentication)) { - manager.acknowledgeAuthentication(true, kind, realm, null, authentication, authentication.getURL()); + if (authentication instanceof SVNSSLAuthentication && (((SVNSSLAuthentication)authentication).getCertificateFile() != null)) { + manager.acknowledgeForSSL(true, authentication); + realm = ((SVNSSLAuthentication)authentication).getCertificateFile().getPath(); } + manager.acknowledgeAuthentication(true, getFromType(authentication), realm, null, authentication, authentication.getURL()); } catch (SvnAuthenticationManager.CredentialsSavedException e) { return e.isSuccess(); } @@ -652,17 +654,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } } - private boolean acknowledgeSSL(SvnAuthenticationManager manager, SVNAuthentication svnAuthentication) throws SVNException { - if (svnAuthentication instanceof SVNSSLAuthentication && (((SVNSSLAuthentication) svnAuthentication).getCertificateFile() != null)) { - manager.acknowledgeForSSL(true, svnAuthentication); - manager.acknowledgeAuthentication(true, getFromType(svnAuthentication), - ((SVNSSLAuthentication) svnAuthentication).getCertificateFile().getPath(), - null, svnAuthentication, svnAuthentication.getURL()); - return true; - } - return false; - } - + @NotNull private static List getKinds(final SVNURL url, boolean passwordRequest) { if (passwordRequest || "http".equals(url.getProtocol())) { return Collections.singletonList(ISVNAuthenticationManager.PASSWORD); @@ -672,8 +664,6 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return Collections.singletonList(ISVNAuthenticationManager.PASSWORD); } else if (url.getProtocol().contains("svn+")) { // todo +- return Arrays.asList(ISVNAuthenticationManager.SSH, ISVNAuthenticationManager.USERNAME); - } else if ("file".equals(url.getProtocol())) { - return Collections.singletonList(ISVNAuthenticationManager.USERNAME); } return Collections.singletonList(ISVNAuthenticationManager.USERNAME); } @@ -684,7 +674,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return myTempDirectory != null ? myTempDirectory : new File(myConfiguration.getConfigurationDirectory()); } - private String getFromType(SVNAuthentication authentication) { + @NotNull + private static String getFromType(SVNAuthentication authentication) { if (authentication instanceof SVNPasswordAuthentication) { return ISVNAuthenticationManager.PASSWORD; } From d14900fe2c97797c5709164ea28b2ea081163cc8 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Tue, 29 Apr 2014 22:11:29 +0400 Subject: [PATCH 57/65] svn: Refactored IdeaSvnkitBasedAuthenticationCallback - removed unused methods related to saving proxy settings to svn config files (currently proxy settings are passed through command line arguments) --- .../jetbrains/idea/svn/IdeaSVNConfigFile.java | 52 +-------- ...IdeaSvnkitBasedAuthenticationCallback.java | 105 +++++++----------- .../commandLine/AuthenticationCallback.java | 32 +----- 3 files changed, 49 insertions(+), 140 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java index 0c0e36f56b1b..03b804496d43 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java @@ -22,9 +22,6 @@ import org.jetbrains.idea.svn.config.ProxyGroup; import org.tmatesoft.svn.core.internal.wc.SVNConfigFile; import java.io.File; -import java.net.InetSocketAddress; -import java.net.PasswordAuthentication; -import java.net.Proxy; import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -49,59 +46,16 @@ public class IdeaSVNConfigFile { myPatternsMap = new HashMap(); } - public static void putProxyIntoServersFile(final File configDir, final String host, final Proxy proxyInfo) { - final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME)); - configFile.updateGroups(); - - String groupName = ensureHostGroup(host, configFile); - - final HashMap map = new HashMap(); - final InetSocketAddress address = ((InetSocketAddress) proxyInfo.address()); - map.put(SvnAuthenticationManager.HTTP_PROXY_HOST, address.getHostName()); - map.put(SvnAuthenticationManager.HTTP_PROXY_PORT, String.valueOf(address.getPort())); - configFile.addGroup(groupName, host + "*", map); - configFile.save(); - } - - @NotNull - public static String ensureHostGroup(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) { - String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); - - if (StringUtil.isEmptyOrSpaces(groupName)) { - groupName = getNewGroupName(host, configFile); - } - - return groupName; - } - @NotNull public static String getNewGroupName(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) { String groupName = host; - final Map groups = configFile.getAllGroups(); + final Map groups = configFile.getAllGroups(); while (StringUtil.isEmptyOrSpaces(groupName) || groups.containsKey(groupName)) { groupName += "1"; } return groupName; } - public static boolean putProxyCredentialsIntoServerFile(@NotNull final File configDir, @NotNull final String host, - @NotNull final PasswordAuthentication authentication) { - final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME)); - configFile.updateGroups(); - - String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile); - // no proxy defined in group -> no sense in password - if (StringUtil.isEmptyOrSpaces(groupName)) return false; - final Map properties = configFile.getAllGroups().get(groupName).getProperties(); - if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_HOST))) return false; - if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_PORT))) return false; - - configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_USERNAME, authentication.getUserName()); - configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_PASSWORD, String.valueOf(authentication.getPassword())); - configFile.save(); - return true; - } - public void updateGroups() { if (myLatestUpdate != myFile.lastModified()) { myPatternsMap.clear(); @@ -155,10 +109,10 @@ public class IdeaSVNConfigFile { public void modifyGroup(final String name, final String patterns, final Collection delete, final Map addOrModify, final boolean isDefault) { - if (! isDefault) { + if (!isDefault) { mySVNConfigFile.setPropertyValue(GROUPS_GROUP_NAME, name, patterns, false); } - final Map deletedPrepared = new HashMap(delete.size()); + final Map deletedPrepared = new HashMap(delete.size()); for (String property : delete) { deletedPrepared.put(property, null); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index 14391ddd2a94..8d5332aa98b3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -34,7 +34,10 @@ import com.intellij.util.net.HttpConfigurable; import com.intellij.util.proxy.CommonProxy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.SvnAuthenticationManager; +import org.jetbrains.idea.svn.SvnBundle; +import org.jetbrains.idea.svn.SvnConfiguration; +import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.commandLine.AuthenticationCallback; import org.jetbrains.idea.svn.dialogs.SimpleCredentialsDialog; import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider; @@ -122,7 +125,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall // we return credentials from cache if they are asked for the first time during command execution, otherwise - user is asked if (data != null && !myRequestedCredentials.contains(getKey(realm, type))) { // we already have credentials in memory cache - result = (T) data; + result = (T)data; myRequestedCredentials.add(getKey(realm, type)); } else { @@ -208,24 +211,6 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall (instance.USE_HTTP_PROXY || instance.USE_PROXY_PAC); } - // TODO: not used - should be removed. - @Override - public boolean persistDataToTmpConfig(final SVNURL repositoryUrl) throws IOException { - // TODO: Make repositoryUrl @NotNull after SvnLineCommand.runWithAuthenticationAttempt refactored - if (repositoryUrl == null) { - return false; - } - - final SvnConfiguration configuration = SvnConfiguration.getInstance(myVcs.getProject()); - initTmpDir(configuration); - - final Proxy proxy = getIdeaDefinedProxy(repositoryUrl); - if (proxy != null){ - IdeaSVNConfigFile.putProxyIntoServersFile(myTempDirectory, repositoryUrl.getHost(), proxy); - } - return true; - } - @Nullable public static Proxy getIdeaDefinedProxy(@NotNull final SVNURL url) { // SVNKit authentication implementation sets repositories as noProxy() to provide custom proxy authentication logic - see for instance, @@ -239,7 +224,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall CommonProxy.getInstance().removeNoProxy(url.getProtocol(), url.getHost(), url.getPort()); final List proxies = CommonProxy.getInstance().select(URI.create(url.toString())); - if (proxies != null && ! proxies.isEmpty()) { + if (proxies != null && !proxies.isEmpty()) { for (Proxy proxy : proxies) { if (HttpConfigurable.isRealProxy(proxy) && Proxy.Type.HTTP.equals(proxy.type())) { return proxy; @@ -254,12 +239,14 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall public PasswordAuthentication getProxyAuthentication(@NotNull SVNURL repositoryUrl) { final Proxy proxy = getIdeaDefinedProxy(repositoryUrl); if (proxy == null) return null; - if (myProxyCredentialsWereReturned){ + if (myProxyCredentialsWereReturned) { // ask loud final HttpConfigurable instance = HttpConfigurable.getInstance(); if (instance.USE_HTTP_PROXY || instance.USE_PROXY_PAC) { - PopupUtil.showBalloonForActiveComponent("Failed to authenticate to proxy. You can change proxy credentials in HTTP proxy settings.", MessageType.ERROR); - } else { + PopupUtil.showBalloonForActiveComponent("Failed to authenticate to proxy. You can change proxy credentials in HTTP proxy settings.", + MessageType.ERROR); + } + else { PopupUtil.showBalloonForActiveComponent("Failed to authenticate to proxy.", MessageType.ERROR); } return null; @@ -271,7 +258,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall .requestPasswordAuthentication(repositoryUrl.getHost(), address.getAddress(), repositoryUrl.getPort(), repositoryUrl.getProtocol(), repositoryUrl.getHost(), repositoryUrl.getProtocol(), new URL(repositoryUrl.toString()), Authenticator.RequestorType.PROXY); - } catch (MalformedURLException e) { + } + catch (MalformedURLException e) { LOG.info(e); return null; } @@ -283,29 +271,6 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return authentication; } - // TODO: not used - should be removed. - @Override - public boolean askProxyCredentials(SVNURL repositoryUrl) { - if (repositoryUrl == null) { - return false; - } - - PasswordAuthentication authentication = getProxyAuthentication(repositoryUrl); - - if (authentication != null) { - // for 'generic' proxy variant (suppose user defined proxy in Subversion config but no password) - try { - initTmpDir(SvnConfiguration.getInstance(myVcs.getProject())); - } - catch (IOException e) { - PopupUtil.showBalloonForActiveComponent("Failed to authenticate to proxy: " + e.getMessage(), MessageType.ERROR); - return false; - } - return IdeaSVNConfigFile.putProxyCredentialsIntoServerFile(myTempDirectory, repositoryUrl.getHost(), authentication); - } - return false; - } - public void reset() { if (myTempDirectory != null) { FileUtil.delete(myTempDirectory); @@ -336,7 +301,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall if (myStoreInUsual) { manager.setArtificialSaving(true); return acknowledge(manager, svnAuthentication); - } else { + } + else { if (myTmpDirManager == null) { initTmpDir(configuration); myTmpDirManager = createTmpManager(); @@ -386,7 +352,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall connection = project.getMessageBus().connect(project); connection.subscribe(SvnAuthenticationManager.AUTHENTICATION_PROVIDER_LISTENER, listener); runnable.run(); - } finally { + } + finally { if (connection != null) { connection.disconnect(); } @@ -417,7 +384,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall @Override protected Boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException { - String stored = (String) passive.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm); + String stored = (String)passive.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm); if (stored == null) return null; CertificateFactory cf; try { @@ -481,9 +448,10 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall protected boolean acknowledge(SvnAuthenticationManager manager, Boolean svnAuthentication) throws SVNException { // we should store certificate, if it wasn't accepted (if temporally tmp) if (myCertificate == null) { // this is if certificate was stored only in passive area - String stored = (String) manager.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm); + String stored = (String)manager.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm); if (StringUtil.isEmptyOrSpaces(stored)) { - throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, "No stored server certificate was found in runtime")); + throw new SVNException( + SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, "No stored server certificate was found in runtime")); } CertificateFactory cf; try { @@ -498,10 +466,10 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall myCertificateRealm = myRealm; } if (myTempDirectory != null && myCertificate != null) { - if (! (myCertificate instanceof X509Certificate)) { + if (!(myCertificate instanceof X509Certificate)) { throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, "Can not store server certificate: " + myCertificate)); } - X509Certificate x509Certificate = (X509Certificate) myCertificate; + X509Certificate x509Certificate = (X509Certificate)myCertificate; String stored; try { stored = SVNBase64.byteArrayToBase64(x509Certificate.getEncoded()); @@ -534,7 +502,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall File tmpFile = SVNFileUtil.createUniqueFile(configDir, "auth", ".tmp", true); try { SVNWCProperties.setProperties(SVNProperties.wrap(map), file, tmpFile, SVNWCProperties.SVN_HASH_TERMINATOR); - } finally { + } + finally { SVNFileUtil.deleteFile(tmpFile); } } @@ -548,7 +517,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall realm = ((SVNSSLAuthentication)authentication).getCertificateFile().getPath(); } manager.acknowledgeAuthentication(true, getFromType(authentication), realm, null, authentication, authentication.getURL()); - } catch (SvnAuthenticationManager.CredentialsSavedException e) { + } + catch (SvnAuthenticationManager.CredentialsSavedException e) { return e.isSuccess(); } return true; @@ -573,7 +543,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall final List kinds = getKinds(url, passwordRequest); for (String kind : kinds) { myKind = kind; - if (! tryAuthenticate()) { + if (!tryAuthenticate()) { return false; } } @@ -583,8 +553,9 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall @Override protected SVNAuthentication getWithPassive(SvnAuthenticationManager passive) throws SVNException { final SVNAuthentication impl = getWithPassiveImpl(passive); - if (impl != null && ! checkAuthOk(impl)) { - clearPassiveCredentials(myRealm, myUrl, impl instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath + if (impl != null && !checkAuthOk(impl)) { + clearPassiveCredentials(myRealm, myUrl, + impl instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath return null; } return impl; @@ -593,7 +564,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall private SVNAuthentication getWithPassiveImpl(SvnAuthenticationManager passive) throws SVNException { try { return passive.getFirstAuthentication(myKind, myRealm, myUrl); - } catch (SVNCancelException e) { + } + catch (SVNCancelException e) { return null; } } @@ -647,7 +619,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall @Override protected boolean acknowledge(SvnAuthenticationManager manager, SVNAuthentication svnAuthentication) throws SVNException { - if (! StringUtil.isEmptyOrSpaces(myRealm2) && ! myRealm2.equals(myRealm)) { + if (!StringUtil.isEmptyOrSpaces(myRealm2) && !myRealm2.equals(myRealm)) { storeCredentials(manager, svnAuthentication, myRealm2); } return storeCredentials(manager, svnAuthentication, myRealm); @@ -658,11 +630,14 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall private static List getKinds(final SVNURL url, boolean passwordRequest) { if (passwordRequest || "http".equals(url.getProtocol())) { return Collections.singletonList(ISVNAuthenticationManager.PASSWORD); - } else if ("https".equals(url.getProtocol())) { + } + else if ("https".equals(url.getProtocol())) { return Collections.singletonList(ISVNAuthenticationManager.SSL); - } else if ("svn".equals(url.getProtocol())) { + } + else if ("svn".equals(url.getProtocol())) { return Collections.singletonList(ISVNAuthenticationManager.PASSWORD); - } else if (url.getProtocol().contains("svn+")) { // todo +- + } + else if (url.getProtocol().contains("svn+")) { // todo +- return Arrays.asList(ISVNAuthenticationManager.SSH, ISVNAuthenticationManager.USERNAME); } return Collections.singletonList(ISVNAuthenticationManager.USERNAME); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthenticationCallback.java index ba6099aae955..11fb831803bb 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/AuthenticationCallback.java @@ -22,7 +22,6 @@ import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.SVNAuthentication; import java.io.File; -import java.io.IOException; import java.net.PasswordAuthentication; /** @@ -46,9 +45,9 @@ public interface AuthenticationCallback { /** * Authenticate for realm and base file belonging to corresponding working copy * - * @param realm - realm that should be used for credential retrieval/storage. + * @param realm - realm that should be used for credential retrieval/storage. * @param repositoryUrl - * @param previousFailed - whether previous credentials were correct + * @param previousFailed - whether previous credentials were correct * @param passwordRequest - if true, password should be asked. Otherwise that may be a certificate (determined by the protocol) * @return false if authentication canceled or was unsuccessful */ @@ -59,7 +58,7 @@ public interface AuthenticationCallback { * For instance, username/password for http/svn protocols. SSL client certificate for two way SSL protocol. * * @param repositoryUrl - * @param type authentication protocol type with svn specific values, like "svn.simple" for http. + * @param type authentication protocol type with svn specific values, like "svn.simple" for http. * @return */ @Nullable @@ -80,7 +79,7 @@ public interface AuthenticationCallback { * Ask user or read from memory storage whether server certificate should be accepted * * @param repositoryUrl - * @param realm - realm that should be used for credential retrieval/storage. + * @param realm - realm that should be used for credential retrieval/storage. * @return true is certificate was accepted */ boolean acceptSSLServerCertificate(SVNURL repositoryUrl, final String realm); @@ -88,9 +87,9 @@ public interface AuthenticationCallback { /** * Clear credentials stored anywhere - in case they were not full, wrong or anything else * - * @param realm - required that credential + * @param realm - required that credential * @param repositoryUrl - * @param password - whether password credential should be deleted or certificate, if protocol might demand certificate + * @param password - whether password credential should be deleted or certificate, if protocol might demand certificate */ void clearPassiveCredentials(String realm, SVNURL repositoryUrl, boolean password); @@ -101,27 +100,8 @@ public interface AuthenticationCallback { */ boolean haveDataForTmpConfig(); - /** - * writes IDEA config settings (that should be written) into tmp config directory - * (now it's IDEA proxy settings) - * - * @param repositoryUrl - * @return true if have written data, false if wasn't able to determine parameters etc - * @throws IOException - */ - boolean persistDataToTmpConfig(SVNURL repositoryUrl) throws IOException; - @Nullable PasswordAuthentication getProxyAuthentication(@NotNull SVNURL repositoryUrl); - /** - * Ask for IDEA-defined proxy credentials, using standard authenticator - * Store data into tmp config - * - * @param repositoryUrl - * @return false if authentication was canceled or related calculations were unsuccessful - */ - boolean askProxyCredentials(SVNURL repositoryUrl); - void reset(); } From a3f190a08ca9a36a3a55d96ae4eee53eb087927e Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 30 Apr 2014 14:44:45 +0400 Subject: [PATCH 58/65] svn: Refactored IdeaSvnkitBasedAuthenticationCallback.AbstractAuthenticator - removed unnecessary parameters from acknowledge() method --- ...IdeaSvnkitBasedAuthenticationCallback.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index 8d5332aa98b3..3bfb009b999b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -300,7 +300,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall if (myStoreInUsual) { manager.setArtificialSaving(true); - return acknowledge(manager, svnAuthentication); + return acknowledge(manager); } else { if (myTmpDirManager == null) { @@ -308,7 +308,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall myTmpDirManager = createTmpManager(); } myTmpDirManager.setArtificialSaving(true); - return acknowledge(myTmpDirManager, svnAuthentication); + return acknowledge(myTmpDirManager); } } catch (IOException e) { @@ -334,7 +334,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall protected abstract T getWithPassive(SvnAuthenticationManager passive) throws SVNException; protected abstract T getWithActive(SvnAuthenticationManager active) throws SVNException; - protected abstract boolean acknowledge(SvnAuthenticationManager manager, T svnAuthentication) throws SVNException; + protected abstract boolean acknowledge(SvnAuthenticationManager manager) throws SVNException; } private void initTmpDir(SvnConfiguration configuration) throws IOException { @@ -445,7 +445,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } @Override - protected boolean acknowledge(SvnAuthenticationManager manager, Boolean svnAuthentication) throws SVNException { + protected boolean acknowledge(SvnAuthenticationManager manager) throws SVNException { // we should store certificate, if it wasn't accepted (if temporally tmp) if (myCertificate == null) { // this is if certificate was stored only in passive area String stored = (String)manager.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm); @@ -552,13 +552,13 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall @Override protected SVNAuthentication getWithPassive(SvnAuthenticationManager passive) throws SVNException { - final SVNAuthentication impl = getWithPassiveImpl(passive); - if (impl != null && !checkAuthOk(impl)) { + myAuthentication = getWithPassiveImpl(passive); + if (myAuthentication != null && !checkAuthOk(myAuthentication)) { clearPassiveCredentials(myRealm, myUrl, - impl instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath - return null; + myAuthentication instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath + myAuthentication = null; } - return impl; + return myAuthentication; } private SVNAuthentication getWithPassiveImpl(SvnAuthenticationManager passive) throws SVNException { @@ -618,11 +618,11 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } @Override - protected boolean acknowledge(SvnAuthenticationManager manager, SVNAuthentication svnAuthentication) throws SVNException { + protected boolean acknowledge(SvnAuthenticationManager manager) throws SVNException { if (!StringUtil.isEmptyOrSpaces(myRealm2) && !myRealm2.equals(myRealm)) { - storeCredentials(manager, svnAuthentication, myRealm2); + storeCredentials(manager, myAuthentication, myRealm2); } - return storeCredentials(manager, svnAuthentication, myRealm); + return storeCredentials(manager, myAuthentication, myRealm); } } From 62b76215ab3e57688e99e4d9c67f72b025d77160 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 30 Apr 2014 16:26:56 +0400 Subject: [PATCH 59/65] svn: Refactored IdeaSvnkitBasedAuthenticationCallback.AbstractAuthenticator - made it not generic --- ...IdeaSvnkitBasedAuthenticationCallback.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index 3bfb009b999b..b5c9f03368d6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -277,7 +277,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } } - private abstract class AbstractAuthenticator { + private abstract class AbstractAuthenticator { protected final SvnVcs myVcs; protected boolean myStoreInUsual; protected SvnAuthenticationManager myTmpDirManager; @@ -292,11 +292,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall final SvnAuthenticationManager manager = configuration.getAuthenticationManager(myVcs); try { - T svnAuthentication = getWithPassive(passive); - if (svnAuthentication == null) { - svnAuthentication = getWithActive(manager); - } - if (svnAuthentication == null) return false; + boolean authenticated = getWithPassive(passive) || getWithActive(manager); + if (!authenticated) return false; if (myStoreInUsual) { manager.setArtificialSaving(true); @@ -332,8 +329,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return interactive; } - protected abstract T getWithPassive(SvnAuthenticationManager passive) throws SVNException; - protected abstract T getWithActive(SvnAuthenticationManager active) throws SVNException; + protected abstract boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException; + protected abstract boolean getWithActive(SvnAuthenticationManager active) throws SVNException; protected abstract boolean acknowledge(SvnAuthenticationManager manager) throws SVNException; } @@ -361,7 +358,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } // plus seems that we also should ask for credentials; but we didn't receive realm name yet - private class SSLServerCertificateAuthenticator extends AbstractAuthenticator { + private class SSLServerCertificateAuthenticator extends AbstractAuthenticator { private SVNURL myUrl; private String myRealm; private String myCertificateRealm; @@ -383,9 +380,9 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } @Override - protected Boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException { + protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException { String stored = (String)passive.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm); - if (stored == null) return null; + if (stored == null) return false; CertificateFactory cf; try { cf = CertificateFactory.getInstance("X509"); @@ -397,11 +394,11 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, e)); } myCertificateRealm = myRealm; - return myCertificate != null ? true : null; + return myCertificate != null; } @Override - protected Boolean getWithActive(final SvnAuthenticationManager active) throws SVNException { + protected boolean getWithActive(final SvnAuthenticationManager active) throws SVNException { doWithSubscribeToAuthProvider(new SvnAuthenticationManager.ISVNAuthenticationProviderListener() { @Override public void requestClientAuthentication(String kind, @@ -441,6 +438,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall ); myStoreInUsual &= myCertificate != null && ISVNAuthenticationProvider.ACCEPTED == myResult; + // TODO: Previous code always returned not null value, so Boolean == null check was always false in tryAuthenticate(). + // TODO: This was most likely error in code - check once again. return ISVNAuthenticationProvider.REJECTED != myResult && myCertificate != null; } @@ -524,7 +523,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return true; } - private class CredentialsAuthenticator extends AbstractAuthenticator { + private class CredentialsAuthenticator extends AbstractAuthenticator { private String myKind; private String myRealm; // sometimes realm string is different (with <>), so store credentials for both strings.. @@ -551,14 +550,14 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } @Override - protected SVNAuthentication getWithPassive(SvnAuthenticationManager passive) throws SVNException { + protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException { myAuthentication = getWithPassiveImpl(passive); if (myAuthentication != null && !checkAuthOk(myAuthentication)) { clearPassiveCredentials(myRealm, myUrl, myAuthentication instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath myAuthentication = null; } - return myAuthentication; + return myAuthentication != null; } private SVNAuthentication getWithPassiveImpl(SvnAuthenticationManager passive) throws SVNException { @@ -579,7 +578,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } @Override - protected SVNAuthentication getWithActive(final SvnAuthenticationManager active) throws SVNException { + protected boolean getWithActive(final SvnAuthenticationManager active) throws SVNException { if (ISVNAuthenticationManager.SSL.equals(myKind)) { doWithSubscribeToAuthProvider(new SvnAuthenticationManager.ISVNAuthenticationProviderListener() { @Override @@ -610,11 +609,12 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } } ); - if (myAuthentication != null) return myAuthentication; + if (myAuthentication != null) return true; } myAuthentication = active.getProvider().requestClientAuthentication(myKind, myUrl, myRealm, null, null, true); myStoreInUsual = myTempDirectory == null && myAuthentication != null && myAuthentication.isStorageAllowed(); - return myAuthentication; + + return myAuthentication != null; } @Override From ec05ae8fa03f01fba36f10074968083d484fb729 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 30 Apr 2014 19:11:15 +0400 Subject: [PATCH 60/65] svn: Refactored IdeaSvnkitBasedAuthenticationCallback.AbstractAuthenticator and inheritors - common parameters moved to base class, @NotNull --- ...IdeaSvnkitBasedAuthenticationCallback.java | 42 +++++++++---------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index b5c9f03368d6..0e3374451255 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -70,14 +70,14 @@ import java.util.Set; * Time: 1:27 PM */ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCallback { - private final SvnVcs myVcs; + @NotNull private final SvnVcs myVcs; private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback"); private File myTempDirectory; private boolean myProxyCredentialsWereReturned; private SvnConfiguration myConfiguration; private final Set myRequestedCredentials; - public IdeaSvnkitBasedAuthenticationCallback(SvnVcs vcs) { + public IdeaSvnkitBasedAuthenticationCallback(@NotNull SvnVcs vcs) { myVcs = vcs; myConfiguration = SvnConfiguration.getInstance(myVcs.getProject()); myRequestedCredentials = ContainerUtil.newHashSet(); @@ -88,7 +88,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall if (repositoryUrl == null) { return false; } - return new CredentialsAuthenticator(myVcs).tryAuthenticate(realm, repositoryUrl, previousFailed, passwordRequest); + return new CredentialsAuthenticator(myVcs, repositoryUrl, realm).tryAuthenticate(passwordRequest); } @Nullable @@ -187,7 +187,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return false; } - return new SSLServerCertificateAuthenticator(myVcs).tryAuthenticate(repositoryUrl, realm); + return new SSLServerCertificateAuthenticator(myVcs, repositoryUrl, realm).tryAuthenticate(); } @Override @@ -278,12 +278,16 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } private abstract class AbstractAuthenticator { - protected final SvnVcs myVcs; + @NotNull protected final SvnVcs myVcs; + @NotNull protected final SVNURL myUrl; + protected final String myRealm; protected boolean myStoreInUsual; protected SvnAuthenticationManager myTmpDirManager; - protected AbstractAuthenticator(SvnVcs vcs) { + protected AbstractAuthenticator(@NotNull SvnVcs vcs, @NotNull SVNURL url, String realm) { myVcs = vcs; + myUrl = url; + myRealm = realm; } protected boolean tryAuthenticate() { @@ -359,24 +363,21 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall // plus seems that we also should ask for credentials; but we didn't receive realm name yet private class SSLServerCertificateAuthenticator extends AbstractAuthenticator { - private SVNURL myUrl; - private String myRealm; private String myCertificateRealm; private String myCredentialsRealm; private Object myCertificate; private int myResult; private SVNAuthentication myAuthentication; - protected SSLServerCertificateAuthenticator(SvnVcs vcs) { - super(vcs); + protected SSLServerCertificateAuthenticator(@NotNull SvnVcs vcs, @NotNull SVNURL url, String realm) { + super(vcs, url, realm); } - public boolean tryAuthenticate(final SVNURL url, final String realm) { - myUrl = url; - myRealm = realm; + @Override + public boolean tryAuthenticate() { myResult = ISVNAuthenticationProvider.ACCEPTED_TEMPORARY; myStoreInUsual = false; - return tryAuthenticate(); + return super.tryAuthenticate(); } @Override @@ -525,21 +526,16 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall private class CredentialsAuthenticator extends AbstractAuthenticator { private String myKind; - private String myRealm; // sometimes realm string is different (with <>), so store credentials for both strings.. private String myRealm2; - private SVNURL myUrl; private SVNAuthentication myAuthentication; - protected CredentialsAuthenticator(SvnVcs vcs) { - super(vcs); + protected CredentialsAuthenticator(@NotNull SvnVcs vcs, @NotNull SVNURL url, @Nullable String realm) { + super(vcs, url, realm == null ? url.getHost() : realm); } - public boolean tryAuthenticate(String realm, SVNURL url, boolean previousFailed, boolean passwordRequest) { - realm = realm == null ? url.getHost() : realm; - myRealm = realm; - myUrl = url; - final List kinds = getKinds(url, passwordRequest); + public boolean tryAuthenticate(boolean passwordRequest) { + final List kinds = getKinds(myUrl, passwordRequest); for (String kind : kinds) { myKind = kind; if (!tryAuthenticate()) { From 2f76fdc480421aba51189fca388f28a552ce589a Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 30 Apr 2014 19:29:38 +0400 Subject: [PATCH 61/65] svn: Refactored IdeaSvnkitBasedAuthenticationCallback.AbstractAuthenticator and inheritors - code simplified --- ...IdeaSvnkitBasedAuthenticationCallback.java | 175 +++++++++--------- 1 file changed, 87 insertions(+), 88 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index 0e3374451255..b8edc88f79c8 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -26,12 +26,12 @@ import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; -import com.intellij.util.ThrowableRunnable; import com.intellij.util.WaitForProgressToShow; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.proxy.CommonProxy; +import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnAuthenticationManager; @@ -333,30 +333,59 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return interactive; } + protected boolean getWithActive(SvnAuthenticationManager active) throws SVNException { + MessageBusConnection connection = null; + try { + final Project project = myVcs.getProject(); + connection = project.getMessageBus().connect(project); + connection.subscribe(SvnAuthenticationManager.AUTHENTICATION_PROVIDER_LISTENER, new MyAuthenticationProviderListener()); + + makeAuthCall(active); + } + finally { + if (connection != null) { + connection.disconnect(); + } + } + + return afterAuthCall(); + } + + protected void makeAuthCall(@NotNull SvnAuthenticationManager manager) throws SVNException { + myVcs.createWCClient(manager).doInfo(myUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD); + } + + protected void acceptServerAuthentication(SVNURL url, String realm, Object certificate, @MagicConstant int acceptResult) { + } + + public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) { + } + + protected abstract boolean afterAuthCall(); + protected abstract boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException; - protected abstract boolean getWithActive(SvnAuthenticationManager active) throws SVNException; + protected abstract boolean acknowledge(SvnAuthenticationManager manager) throws SVNException; - } - private void initTmpDir(SvnConfiguration configuration) throws IOException { - if (myTempDirectory == null) { - myTempDirectory = FileUtil.createTempDirectory("tmp", "Subversion"); - FileUtil.copyDir(new File(configuration.getConfigurationDirectory()), myTempDirectory); - } - } + private class MyAuthenticationProviderListener implements SvnAuthenticationManager.ISVNAuthenticationProviderListener { + @Override + public void requestClientAuthentication(String kind, + SVNURL url, + String realm, + SVNErrorMessage errorMessage, + SVNAuthentication previousAuth, + boolean authMayBeStored, + SVNAuthentication authentication) { + AbstractAuthenticator.this.requestClientAuthentication(url, realm, authentication); + } - private void doWithSubscribeToAuthProvider(SvnAuthenticationManager.ISVNAuthenticationProviderListener listener, - final ThrowableRunnable runnable) throws SVNException { - MessageBusConnection connection = null; - try { - final Project project = myVcs.getProject(); - connection = project.getMessageBus().connect(project); - connection.subscribe(SvnAuthenticationManager.AUTHENTICATION_PROVIDER_LISTENER, listener); - runnable.run(); - } - finally { - if (connection != null) { - connection.disconnect(); + @Override + public void acceptServerAuthentication(SVNURL url, + String realm, + Object certificate, + boolean resultMayBeStored, + @MagicConstant int acceptResult) { + AbstractAuthenticator.this.acceptServerAuthentication(url, realm, certificate, acceptResult); } } } @@ -399,45 +428,25 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } @Override - protected boolean getWithActive(final SvnAuthenticationManager active) throws SVNException { - doWithSubscribeToAuthProvider(new SvnAuthenticationManager.ISVNAuthenticationProviderListener() { - @Override - public void requestClientAuthentication(String kind, - SVNURL url, - String realm, - SVNErrorMessage errorMessage, - SVNAuthentication previousAuth, - boolean authMayBeStored, - SVNAuthentication authentication) { - if (!myUrl.equals(url)) return; - myCredentialsRealm = realm; - myAuthentication = authentication; - if (myAuthentication != null) { - myStoreInUsual &= myAuthentication.isStorageAllowed(); - } - } + public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) { + if (!myUrl.equals(url)) return; + myCredentialsRealm = realm; + myAuthentication = authentication; + if (myAuthentication != null) { + myStoreInUsual &= myAuthentication.isStorageAllowed(); + } + } - @Override - public void acceptServerAuthentication(SVNURL url, - String realm, - Object certificate, - boolean resultMayBeStored, - int accepted) { - if (!myUrl.equals(url)) return; - myCertificateRealm = realm; - myCertificate = certificate; - myResult = accepted; - } - }, new ThrowableRunnable() { - @Override - public void run() throws SVNException { - // NOTE: DO NOT replace this call - SSL authentication highly tied to SVNKit - myVcs.createWCClient(active).doInfo(myUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD); - //myVcs.getInfo(myUrl, SVNRevision.HEAD, active); - } - } - ); + @Override + public void acceptServerAuthentication(SVNURL url, String realm, Object certificate, @MagicConstant int acceptResult) { + if (!myUrl.equals(url)) return; + myCertificateRealm = realm; + myCertificate = certificate; + myResult = acceptResult; + } + @Override + protected boolean afterAuthCall() { myStoreInUsual &= myCertificate != null && ISVNAuthenticationProvider.ACCEPTED == myResult; // TODO: Previous code always returned not null value, so Boolean == null check was always false in tryAuthenticate(). // TODO: This was most likely error in code - check once again. @@ -576,36 +585,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall @Override protected boolean getWithActive(final SvnAuthenticationManager active) throws SVNException { if (ISVNAuthenticationManager.SSL.equals(myKind)) { - doWithSubscribeToAuthProvider(new SvnAuthenticationManager.ISVNAuthenticationProviderListener() { - @Override - public void requestClientAuthentication(String kind, - SVNURL url, - String realm, - SVNErrorMessage errorMessage, - SVNAuthentication previousAuth, - boolean authMayBeStored, - SVNAuthentication authentication) { - if (!myUrl.equals(url)) return; - myAuthentication = authentication; - myRealm2 = realm; - myStoreInUsual = myAuthentication != null && myAuthentication.isStorageAllowed(); - } - - @Override - public void acceptServerAuthentication(SVNURL url, - String realm, - Object certificate, - boolean resultMayBeStored, - int accepted) { - } - }, new ThrowableRunnable() { - @Override - public void run() throws SVNException { - myVcs.createWCClient(active).doInfo(myUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD); - } - } - ); - if (myAuthentication != null) return true; + if (super.getWithActive(active)) return true; } myAuthentication = active.getProvider().requestClientAuthentication(myKind, myUrl, myRealm, null, null, true); myStoreInUsual = myTempDirectory == null && myAuthentication != null && myAuthentication.isStorageAllowed(); @@ -613,6 +593,18 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return myAuthentication != null; } + public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) { + if (!myUrl.equals(url)) return; + myAuthentication = authentication; + myRealm2 = realm; + myStoreInUsual = myAuthentication != null && myAuthentication.isStorageAllowed(); + } + + @Override + protected boolean afterAuthCall() { + return myAuthentication != null; + } + @Override protected boolean acknowledge(SvnAuthenticationManager manager) throws SVNException { if (!StringUtil.isEmptyOrSpaces(myRealm2) && !myRealm2.equals(myRealm)) { @@ -645,6 +637,13 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return myTempDirectory != null ? myTempDirectory : new File(myConfiguration.getConfigurationDirectory()); } + private void initTmpDir(SvnConfiguration configuration) throws IOException { + if (myTempDirectory == null) { + myTempDirectory = FileUtil.createTempDirectory("tmp", "Subversion"); + FileUtil.copyDir(new File(configuration.getConfigurationDirectory()), myTempDirectory); + } + } + @NotNull private static String getFromType(SVNAuthentication authentication) { if (authentication instanceof SVNPasswordAuthentication) { From e663caac4683242ef0899fba71f03cf9667852a1 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 30 Apr 2014 20:42:48 +0400 Subject: [PATCH 62/65] svn: Refactored IdeaSvnkitBasedAuthenticationCallback - code simplified, duplication removed --- ...IdeaSvnkitBasedAuthenticationCallback.java | 166 +++++++++--------- 1 file changed, 84 insertions(+), 82 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index b8edc88f79c8..96b1df3b9967 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -54,10 +54,7 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.net.*; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; +import java.security.cert.*; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -237,38 +234,46 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall @Override @Nullable public PasswordAuthentication getProxyAuthentication(@NotNull SVNURL repositoryUrl) { - final Proxy proxy = getIdeaDefinedProxy(repositoryUrl); - if (proxy == null) return null; - if (myProxyCredentialsWereReturned) { - // ask loud - final HttpConfigurable instance = HttpConfigurable.getInstance(); - if (instance.USE_HTTP_PROXY || instance.USE_PROXY_PAC) { - PopupUtil.showBalloonForActiveComponent("Failed to authenticate to proxy. You can change proxy credentials in HTTP proxy settings.", - MessageType.ERROR); + Proxy proxy = getIdeaDefinedProxy(repositoryUrl); + PasswordAuthentication result = null; + + if (proxy != null) { + if (myProxyCredentialsWereReturned) { + showFailedAuthenticateProxy(); } else { - PopupUtil.showBalloonForActiveComponent("Failed to authenticate to proxy.", MessageType.ERROR); + result = getProxyAuthentication(proxy, repositoryUrl); + myProxyCredentialsWereReturned = result != null; } - return null; } - final InetSocketAddress address = (InetSocketAddress)proxy.address(); - final PasswordAuthentication authentication; + + return result; + } + + private static void showFailedAuthenticateProxy() { + HttpConfigurable instance = HttpConfigurable.getInstance(); + String message = instance.USE_HTTP_PROXY || instance.USE_PROXY_PAC + ? "Failed to authenticate to proxy. You can change proxy credentials in HTTP proxy settings." + : "Failed to authenticate to proxy."; + + PopupUtil.showBalloonForActiveComponent(message, MessageType.ERROR); + } + + @Nullable + private static PasswordAuthentication getProxyAuthentication(@NotNull Proxy proxy, @NotNull SVNURL repositoryUrl) { + PasswordAuthentication result = null; + try { - authentication = Authenticator - .requestPasswordAuthentication(repositoryUrl.getHost(), address.getAddress(), repositoryUrl.getPort(), repositoryUrl.getProtocol(), - repositoryUrl.getHost(), repositoryUrl.getProtocol(), new URL(repositoryUrl.toString()), - Authenticator.RequestorType.PROXY); + result = Authenticator.requestPasswordAuthentication(repositoryUrl.getHost(), ((InetSocketAddress)proxy.address()).getAddress(), + repositoryUrl.getPort(), repositoryUrl.getProtocol(), repositoryUrl.getHost(), + repositoryUrl.getProtocol(), new URL(repositoryUrl.toString()), + Authenticator.RequestorType.PROXY); } catch (MalformedURLException e) { LOG.info(e); - return null; } - if (authentication != null) { - myProxyCredentialsWereReturned = true; - } - - return authentication; + return result; } public void reset() { @@ -291,26 +296,16 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } protected boolean tryAuthenticate() { - final SvnConfiguration configuration = SvnConfiguration.getInstance(myVcs.getProject()); - final SvnAuthenticationManager passive = configuration.getPassiveAuthenticationManager(myVcs.getProject()); - final SvnAuthenticationManager manager = configuration.getAuthenticationManager(myVcs); + final SvnAuthenticationManager passive = myVcs.getSvnConfiguration().getPassiveAuthenticationManager(myVcs.getProject()); + final SvnAuthenticationManager active = myVcs.getSvnConfiguration().getAuthenticationManager(myVcs); try { - boolean authenticated = getWithPassive(passive) || getWithActive(manager); + boolean authenticated = getWithPassive(passive) || getWithActive(active); if (!authenticated) return false; - if (myStoreInUsual) { - manager.setArtificialSaving(true); - return acknowledge(manager); - } - else { - if (myTmpDirManager == null) { - initTmpDir(configuration); - myTmpDirManager = createTmpManager(); - } - myTmpDirManager.setArtificialSaving(true); - return acknowledge(myTmpDirManager); - } + SvnAuthenticationManager manager = myStoreInUsual ? active : createTmpManager(); + manager.setArtificialSaving(true); + return acknowledge(manager); } catch (IOException e) { LOG.info(e); @@ -324,13 +319,16 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } } - protected SvnAuthenticationManager createTmpManager() { - final SvnAuthenticationManager interactive = new SvnAuthenticationManager(myVcs.getProject(), myTempDirectory); + @NotNull + protected SvnAuthenticationManager createTmpManager() throws IOException { + if (myTmpDirManager == null) { + initTmpDir(myVcs.getSvnConfiguration()); + myTmpDirManager = new SvnAuthenticationManager(myVcs.getProject(), myTempDirectory); + myTmpDirManager.setRuntimeStorage(SvnConfiguration.RUNTIME_AUTH_CACHE); + myTmpDirManager.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(myVcs, myTmpDirManager)); + } - interactive.setRuntimeStorage(SvnConfiguration.RUNTIME_AUTH_CACHE); - interactive.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(myVcs, interactive)); - - return interactive; + return myTmpDirManager; } protected boolean getWithActive(SvnAuthenticationManager active) throws SVNException { @@ -413,18 +411,10 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException { String stored = (String)passive.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm); if (stored == null) return false; - CertificateFactory cf; - try { - cf = CertificateFactory.getInstance("X509"); - final byte[] buffer = new byte[stored.length()]; - SVNBase64.base64ToByteArray(new StringBuffer(stored), buffer); - myCertificate = cf.generateCertificate(new ByteArrayInputStream(buffer)); - } - catch (CertificateException e) { - throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, e)); - } + + myCertificate = createCertificate(stored); myCertificateRealm = myRealm; - return myCertificate != null; + return true; } @Override @@ -462,32 +452,12 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall throw new SVNException( SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, "No stored server certificate was found in runtime")); } - CertificateFactory cf; - try { - cf = CertificateFactory.getInstance("X509"); - final byte[] buffer = new byte[stored.length()]; - SVNBase64.base64ToByteArray(new StringBuffer(stored), buffer); - myCertificate = cf.generateCertificate(new ByteArrayInputStream(buffer)); - } - catch (CertificateException e) { - throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, e)); - } + myCertificate = createCertificate(stored); myCertificateRealm = myRealm; } if (myTempDirectory != null && myCertificate != null) { - if (!(myCertificate instanceof X509Certificate)) { - throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, "Can not store server certificate: " + myCertificate)); - } - X509Certificate x509Certificate = (X509Certificate)myCertificate; - String stored; - try { - stored = SVNBase64.byteArrayToBase64(x509Certificate.getEncoded()); - } - catch (CertificateEncodingException e) { - throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e)); - } - int failures = SVNSSLUtil.getServerCertificateFailures(x509Certificate, myUrl.getHost()); - storeServerCertificate(myTempDirectory, myCertificateRealm, stored, failures); + storeServerCertificate(); + if (myAuthentication != null) { final String realm = myCredentialsRealm == null ? myCertificateRealm : myCredentialsRealm; return storeCredentials(manager, myAuthentication, realm); @@ -496,6 +466,38 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return true; } + @NotNull + private Certificate createCertificate(@NotNull String stored) throws SVNException { + CertificateFactory factory; + try { + factory = CertificateFactory.getInstance("X509"); + final byte[] buffer = new byte[stored.length()]; + SVNBase64.base64ToByteArray(new StringBuffer(stored), buffer); + + return factory.generateCertificate(new ByteArrayInputStream(buffer)); + } + catch (CertificateException e) { + throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, e)); + } + } + + private void storeServerCertificate() throws SVNException { + if (!(myCertificate instanceof X509Certificate)) { + throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, "Can not store server certificate: " + myCertificate)); + } + X509Certificate x509Certificate = (X509Certificate)myCertificate; + String stored; + try { + stored = SVNBase64.byteArrayToBase64(x509Certificate.getEncoded()); + } + catch (CertificateEncodingException e) { + throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e)); + } + + int failures = SVNSSLUtil.getServerCertificateFailures(x509Certificate, myUrl.getHost()); + storeServerCertificate(myTempDirectory, myCertificateRealm, stored, failures); + } + private void storeServerCertificate(final File configDir, String realm, String data, int failures) throws SVNException { //noinspection ResultOfMethodCallIgnored configDir.mkdirs(); From ac99e82e0f291d65104013da4031142633b30bdb Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 30 Apr 2014 21:00:14 +0400 Subject: [PATCH 63/65] svn: Refactored IdeaSvnkitBasedAuthenticationCallback - made inner classes to be static --- ...IdeaSvnkitBasedAuthenticationCallback.java | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java index 96b1df3b9967..14bf4bec647a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java @@ -80,12 +80,22 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall myRequestedCredentials = ContainerUtil.newHashSet(); } + @NotNull + public SvnVcs getVcs() { + return myVcs; + } + + @Nullable + public File getTempDirectory() { + return myTempDirectory; + } + @Override public boolean authenticateFor(String realm, SVNURL repositoryUrl, boolean previousFailed, boolean passwordRequest) { if (repositoryUrl == null) { return false; } - return new CredentialsAuthenticator(myVcs, repositoryUrl, realm).tryAuthenticate(passwordRequest); + return new CredentialsAuthenticator(this, repositoryUrl, realm).tryAuthenticate(passwordRequest); } @Nullable @@ -184,7 +194,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return false; } - return new SSLServerCertificateAuthenticator(myVcs, repositoryUrl, realm).tryAuthenticate(); + return new SSLServerCertificateAuthenticator(this, repositoryUrl, realm).tryAuthenticate(); } @Override @@ -282,15 +292,17 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } } - private abstract class AbstractAuthenticator { + private static abstract class AbstractAuthenticator { + @NotNull protected final IdeaSvnkitBasedAuthenticationCallback myAuthService; @NotNull protected final SvnVcs myVcs; @NotNull protected final SVNURL myUrl; protected final String myRealm; protected boolean myStoreInUsual; protected SvnAuthenticationManager myTmpDirManager; - protected AbstractAuthenticator(@NotNull SvnVcs vcs, @NotNull SVNURL url, String realm) { - myVcs = vcs; + protected AbstractAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, @NotNull SVNURL url, String realm) { + myAuthService = authService; + myVcs = myAuthService.getVcs(); myUrl = url; myRealm = realm; } @@ -322,8 +334,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall @NotNull protected SvnAuthenticationManager createTmpManager() throws IOException { if (myTmpDirManager == null) { - initTmpDir(myVcs.getSvnConfiguration()); - myTmpDirManager = new SvnAuthenticationManager(myVcs.getProject(), myTempDirectory); + myAuthService.initTmpDir(myVcs.getSvnConfiguration()); + myTmpDirManager = new SvnAuthenticationManager(myVcs.getProject(), myAuthService.getTempDirectory()); myTmpDirManager.setRuntimeStorage(SvnConfiguration.RUNTIME_AUTH_CACHE); myTmpDirManager.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(myVcs, myTmpDirManager)); } @@ -389,15 +401,17 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } // plus seems that we also should ask for credentials; but we didn't receive realm name yet - private class SSLServerCertificateAuthenticator extends AbstractAuthenticator { + private static class SSLServerCertificateAuthenticator extends AbstractAuthenticator { private String myCertificateRealm; private String myCredentialsRealm; private Object myCertificate; private int myResult; private SVNAuthentication myAuthentication; - protected SSLServerCertificateAuthenticator(@NotNull SvnVcs vcs, @NotNull SVNURL url, String realm) { - super(vcs, url, realm); + protected SSLServerCertificateAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, + @NotNull SVNURL url, + String realm) { + super(authService, url, realm); } @Override @@ -455,7 +469,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall myCertificate = createCertificate(stored); myCertificateRealm = myRealm; } - if (myTempDirectory != null && myCertificate != null) { + if (myAuthService.getTempDirectory() != null && myCertificate != null) { storeServerCertificate(); if (myAuthentication != null) { @@ -495,7 +509,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } int failures = SVNSSLUtil.getServerCertificateFailures(x509Certificate, myUrl.getHost()); - storeServerCertificate(myTempDirectory, myCertificateRealm, stored, failures); + storeServerCertificate(myAuthService.getTempDirectory(), myCertificateRealm, stored, failures); } private void storeServerCertificate(final File configDir, String realm, String data, int failures) throws SVNException { @@ -535,14 +549,16 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return true; } - private class CredentialsAuthenticator extends AbstractAuthenticator { + private static class CredentialsAuthenticator extends AbstractAuthenticator { private String myKind; // sometimes realm string is different (with <>), so store credentials for both strings.. private String myRealm2; private SVNAuthentication myAuthentication; - protected CredentialsAuthenticator(@NotNull SvnVcs vcs, @NotNull SVNURL url, @Nullable String realm) { - super(vcs, url, realm == null ? url.getHost() : realm); + protected CredentialsAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, + @NotNull SVNURL url, + @Nullable String realm) { + super(authService, url, realm == null ? url.getHost() : realm); } public boolean tryAuthenticate(boolean passwordRequest) { @@ -560,8 +576,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException { myAuthentication = getWithPassiveImpl(passive); if (myAuthentication != null && !checkAuthOk(myAuthentication)) { - clearPassiveCredentials(myRealm, myUrl, - myAuthentication instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath + myAuthService.clearPassiveCredentials(myRealm, myUrl, + myAuthentication instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath myAuthentication = null; } return myAuthentication != null; @@ -590,7 +606,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall if (super.getWithActive(active)) return true; } myAuthentication = active.getProvider().requestClientAuthentication(myKind, myUrl, myRealm, null, null, true); - myStoreInUsual = myTempDirectory == null && myAuthentication != null && myAuthentication.isStorageAllowed(); + myStoreInUsual = myAuthService.getTempDirectory() == null && myAuthentication != null && myAuthentication.isStorageAllowed(); return myAuthentication != null; } @@ -639,7 +655,7 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall return myTempDirectory != null ? myTempDirectory : new File(myConfiguration.getConfigurationDirectory()); } - private void initTmpDir(SvnConfiguration configuration) throws IOException { + public void initTmpDir(SvnConfiguration configuration) throws IOException { if (myTempDirectory == null) { myTempDirectory = FileUtil.createTempDirectory("tmp", "Subversion"); FileUtil.copyDir(new File(configuration.getConfigurationDirectory()), myTempDirectory); From d5a0f9e548e24db3b50de4cac7db8015acffb566 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 30 Apr 2014 21:24:15 +0400 Subject: [PATCH 64/65] svn: Moved several authentication-related classes to "org.jetbrains.idea.svn.auth" package --- .../src/org/jetbrains/idea/svn/SvnConfigurable.java | 1 + .../src/org/jetbrains/idea/svn/SvnConfiguration.java | 5 +++-- plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java | 1 + .../src/org/jetbrains/idea/svn/api/BaseSvnClient.java | 2 +- .../IdeaSvnkitBasedAuthenticationCallback.java | 6 ++---- .../idea/svn/{ => auth}/ProxySvnAuthentication.java | 2 +- .../idea/svn/{ => auth}/SvnAuthenticationManager.java | 8 +++----- .../idea/svn/{ => auth}/SvnAuthenticationNotifier.java | 6 +++--- .../svn/{dialogs => auth}/SvnAuthenticationProvider.java | 4 +--- .../SvnInteractiveAuthenticationProvider.java | 7 +++---- .../jetbrains/idea/svn/commandLine/CommandRuntime.java | 1 + .../org/jetbrains/idea/svn/commandLine/CommandUtil.java | 3 --- .../org/jetbrains/idea/svn/commandLine/ProxyModule.java | 4 ++-- .../jetbrains/idea/svn/config/RepositoryUrlFilter.java | 2 +- .../jetbrains/idea/svn/dialogs/SSHCredentialsDialog.java | 2 +- .../org/jetbrains/idea/svn/dialogs/ServerSSLDialog.java | 2 +- .../idea/svn/dialogs/UserNameCredentialsDialog.java | 2 +- .../idea/svn/dialogs/browserCache/RepositoryLoader.java | 2 +- .../idea/svn/history/SingleCommittedListProvider.java | 1 + .../org/jetbrains/idea/svn/SvnAuthenticationTest.java | 5 +---- .../org/jetbrains/idea/svn/SvnNativeClientAuthTest.java | 2 ++ .../org/jetbrains/idea/svn/SvnProtocolsTest.java | 1 + .../idea/svn/SvnTestInteractiveAuthentication.java | 1 + .../org/jetbrains/idea/svn16/SvnAuthenticationTest.java | 6 +++--- 24 files changed, 36 insertions(+), 40 deletions(-) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{checkin => auth}/IdeaSvnkitBasedAuthenticationCallback.java (98%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{ => auth}/ProxySvnAuthentication.java (98%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{ => auth}/SvnAuthenticationManager.java (99%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{ => auth}/SvnAuthenticationNotifier.java (98%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{dialogs => auth}/SvnAuthenticationProvider.java (96%) rename plugins/svn4idea/src/org/jetbrains/idea/svn/{dialogs => auth}/SvnInteractiveAuthenticationProvider.java (97%) diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java index 71709f783055..adfbe0880d33 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java @@ -39,6 +39,7 @@ import com.intellij.util.Consumer; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.auth.SvnAuthenticationNotifier; import org.jetbrains.idea.svn.config.SvnConfigureProxiesDialog; import javax.swing.*; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java index 6c0be5f0a3dc..b782f5a657d3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java @@ -22,9 +22,10 @@ import com.intellij.openapi.components.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.*; import com.intellij.openapi.vcs.changes.VcsAnnotationRefresher; +import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; import org.jetbrains.idea.svn.config.SvnServerFileKeys; -import org.jetbrains.idea.svn.dialogs.SvnAuthenticationProvider; -import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider; +import org.jetbrains.idea.svn.auth.SvnAuthenticationProvider; +import org.jetbrains.idea.svn.auth.SvnInteractiveAuthenticationProvider; import org.jetbrains.idea.svn.update.MergeRootInfo; import org.jetbrains.idea.svn.update.UpdateRootInfo; import org.tmatesoft.svn.core.SVNDepth; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java index ba425af47f26..54616f46c1a6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java @@ -73,6 +73,7 @@ import org.jetbrains.idea.svn.annotate.SvnAnnotationProvider; import org.jetbrains.idea.svn.api.ClientFactory; import org.jetbrains.idea.svn.api.CmdClientFactory; import org.jetbrains.idea.svn.api.SvnKitClientFactory; +import org.jetbrains.idea.svn.auth.SvnAuthenticationNotifier; import org.jetbrains.idea.svn.checkin.SvnCheckinEnvironment; import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider; import org.jetbrains.idea.svn.commandLine.SvnExecutableChecker; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java index b788d3074ec2..bb8c613c8135 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java @@ -6,7 +6,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.WorkingCopyFormat; -import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback; +import org.jetbrains.idea.svn.auth.IdeaSvnkitBasedAuthenticationCallback; import org.jetbrains.idea.svn.commandLine.*; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.ISVNEventHandler; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/IdeaSvnkitBasedAuthenticationCallback.java similarity index 98% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/auth/IdeaSvnkitBasedAuthenticationCallback.java index 14bf4bec647a..feed4915ff5e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/IdeaSvnkitBasedAuthenticationCallback.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.checkin; +package org.jetbrains.idea.svn.auth; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; @@ -34,13 +34,11 @@ import com.intellij.util.proxy.CommonProxy; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnAuthenticationManager; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.commandLine.AuthenticationCallback; import org.jetbrains.idea.svn.dialogs.SimpleCredentialsDialog; -import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.auth.*; import org.tmatesoft.svn.core.internal.util.SVNBase64; @@ -68,7 +66,7 @@ import java.util.Set; */ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCallback { @NotNull private final SvnVcs myVcs; - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback"); + private static final Logger LOG = Logger.getInstance(IdeaSvnkitBasedAuthenticationCallback.class); private File myTempDirectory; private boolean myProxyCredentialsWereReturned; private SvnConfiguration myConfiguration; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/ProxySvnAuthentication.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/ProxySvnAuthentication.java similarity index 98% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/ProxySvnAuthentication.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/auth/ProxySvnAuthentication.java index 5e0c618738d4..c34f085c90ae 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/ProxySvnAuthentication.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/ProxySvnAuthentication.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn; +package org.jetbrains.idea.svn.auth; import org.tmatesoft.svn.core.auth.*; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationManager.java similarity index 99% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationManager.java index 626cf6241eea..e844374cf341 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationManager.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn; +package org.jetbrains.idea.svn.auth; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; @@ -42,9 +42,7 @@ import com.intellij.util.ui.UIUtil; import com.trilead.ssh2.auth.AgentProxy; import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.auth.ProviderType; -import org.jetbrains.idea.svn.auth.SvnAuthenticationInteraction; -import org.jetbrains.idea.svn.auth.SvnAuthenticationListener; +import org.jetbrains.idea.svn.*; import org.jetbrains.idea.svn.config.ProxyGroup; import org.jetbrains.idea.svn.config.SvnServerFileKeys; import org.tmatesoft.svn.core.SVNErrorMessage; @@ -64,7 +62,7 @@ import java.util.*; * @author alex */ public class SvnAuthenticationManager extends DefaultSVNAuthenticationManager implements SvnAuthenticationListener, ISVNAuthenticationManagerExt { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnAuthenticationManager"); + private static final Logger LOG = Logger.getInstance(SvnAuthenticationManager.class); // while Mac storage not working for IDEA, we use this key to check whether to prompt abt plaintext or just store public static final String SVN_SSH = "svn+ssh"; public static final String HTTP = "http"; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java similarity index 98% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java index 5b84aa234d38..94889bdc3eeb 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationNotifier.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn; +package org.jetbrains.idea.svn.auth; import com.intellij.notification.NotificationType; import com.intellij.openapi.application.Application; @@ -44,7 +44,7 @@ import com.intellij.util.net.HttpConfigurable; import com.intellij.util.proxy.CommonProxy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider; +import org.jetbrains.idea.svn.*; import org.tmatesoft.svn.core.SVNAuthenticationException; import org.tmatesoft.svn.core.SVNCancelException; import org.tmatesoft.svn.core.SVNException; @@ -64,7 +64,7 @@ import java.util.List; import java.util.Timer; public class SvnAuthenticationNotifier extends GenericNotifierImpl { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnAuthenticationNotifier"); + private static final Logger LOG = Logger.getInstance(SvnAuthenticationNotifier.class); private static final List ourAuthKinds = Arrays.asList(ISVNAuthenticationManager.PASSWORD, ISVNAuthenticationManager.SSH, ISVNAuthenticationManager.SSL, ISVNAuthenticationManager.USERNAME, "svn.ssl.server", "svn.ssh.server"); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnAuthenticationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationProvider.java similarity index 96% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnAuthenticationProvider.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationProvider.java index 04868ae990b8..3ad9de7badaf 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnAuthenticationProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnAuthenticationProvider.java @@ -13,13 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.dialogs; +package org.jetbrains.idea.svn.auth; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.util.SystemProperties; -import org.jetbrains.idea.svn.SvnAuthenticationManager; -import org.jetbrains.idea.svn.SvnAuthenticationNotifier; import org.jetbrains.idea.svn.SvnVcs; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNURL; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnInteractiveAuthenticationProvider.java similarity index 97% rename from plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java rename to plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnInteractiveAuthenticationProvider.java index b39dddedc632..de2c007b7879 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SvnInteractiveAuthenticationProvider.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.jetbrains.idea.svn.dialogs; +package org.jetbrains.idea.svn.auth; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; @@ -31,11 +31,10 @@ import com.jcraft.jsch.agentproxy.ConnectorFactory; import com.jcraft.jsch.agentproxy.TrileadAgentProxy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnAuthenticationManager; import org.jetbrains.idea.svn.SvnBundle; import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.auth.ProviderType; +import org.jetbrains.idea.svn.dialogs.*; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.*; @@ -47,7 +46,7 @@ import java.lang.reflect.InvocationTargetException; import java.security.cert.X509Certificate; public class SvnInteractiveAuthenticationProvider implements ISVNAuthenticationProvider { - private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider"); + private static final Logger LOG = Logger.getInstance(SvnInteractiveAuthenticationProvider.class); private final Project myProject; private static final ThreadLocal myCallState = new ThreadLocal(); private final SvnAuthenticationManager myManager; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java index a25c9caecbff..5cc66e0a3983 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java @@ -24,6 +24,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; import org.tmatesoft.svn.core.SVNURL; import java.io.File; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java index bd223001e5a4..0ec9589b5129 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java @@ -2,11 +2,8 @@ package org.jetbrains.idea.svn.commandLine; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vcs.VcsException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnVcs; -import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.wc.SVNDiffOptions; import org.tmatesoft.svn.core.wc.SVNRevision; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java index 421a7346b6de..11bb9b654523 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java @@ -19,8 +19,8 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.IdeaSVNConfigFile; -import org.jetbrains.idea.svn.SvnAuthenticationManager; -import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback; +import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; +import org.jetbrains.idea.svn.auth.IdeaSvnkitBasedAuthenticationCallback; import org.tmatesoft.svn.core.SVNURL; import java.net.InetSocketAddress; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/config/RepositoryUrlFilter.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/config/RepositoryUrlFilter.java index b9bb3b717012..0dd0677e470c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/config/RepositoryUrlFilter.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/config/RepositoryUrlFilter.java @@ -16,7 +16,7 @@ package org.jetbrains.idea.svn.config; import org.jetbrains.idea.svn.SvnApplicationSettings; -import org.jetbrains.idea.svn.SvnAuthenticationManager; +import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; import java.util.ArrayList; import java.util.Collection; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SSHCredentialsDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SSHCredentialsDialog.java index bf77ced4b1bb..5de8ac04ba4f 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SSHCredentialsDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SSHCredentialsDialog.java @@ -76,7 +76,7 @@ public class SSHCredentialsDialog extends DialogWrapper implements ActionListene @NonNls private static final String HELP_ID = "vcs.subversion.authentication"; private boolean myKeyFileEmptyOrCorrect; - protected SSHCredentialsDialog(Project project, + public SSHCredentialsDialog(Project project, String realm, String userName, boolean allowSave, diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ServerSSLDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ServerSSLDialog.java index 3506e5859a4c..fc6bb33c4db3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ServerSSLDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ServerSSLDialog.java @@ -39,7 +39,7 @@ public class ServerSSLDialog extends DialogWrapper { private int myResult; @NonNls public static final String ALGORITHM_SHA1 = "SHA1"; - protected ServerSSLDialog(final Project project, X509Certificate cert, boolean store) { + public ServerSSLDialog(final Project project, X509Certificate cert, boolean store) { super(project, true); myCertificate = cert; myResult = ISVNAuthenticationProvider.REJECTED; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UserNameCredentialsDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UserNameCredentialsDialog.java index 3896c020f880..212c5ce7130e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UserNameCredentialsDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/UserNameCredentialsDialog.java @@ -39,7 +39,7 @@ public class UserNameCredentialsDialog extends DialogWrapper implements Document @NonNls private static final String HELP_ID = "vcs.subversion.authentication"; - protected UserNameCredentialsDialog(Project project) { + public UserNameCredentialsDialog(Project project) { super(project, true); setResizable(false); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browserCache/RepositoryLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browserCache/RepositoryLoader.java index 83185fef189f..d2f8b633773b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browserCache/RepositoryLoader.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browserCache/RepositoryLoader.java @@ -23,7 +23,7 @@ import com.intellij.openapi.util.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.dialogs.RepositoryTreeNode; -import org.jetbrains.idea.svn.dialogs.SvnAuthenticationProvider; +import org.jetbrains.idea.svn.auth.SvnAuthenticationProvider; import org.tmatesoft.svn.core.ISVNDirEntryHandler; import org.tmatesoft.svn.core.SVNDirEntry; import org.tmatesoft.svn.core.SVNErrorMessage; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SingleCommittedListProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SingleCommittedListProvider.java index e62b8e041623..6ac6adc3b5cd 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SingleCommittedListProvider.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SingleCommittedListProvider.java @@ -28,6 +28,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.vcsUtil.VcsUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.*; +import org.jetbrains.idea.svn.auth.SvnAuthenticationNotifier; import org.jetbrains.idea.svn.commandLine.SvnBindException; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.wc.SVNRevision; diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java index f3552e99c392..bf0c9eebb1bb 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java @@ -24,10 +24,7 @@ import com.intellij.testFramework.PlatformTestCase; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.ui.UIUtil; import junit.framework.Assert; -import org.jetbrains.idea.svn.auth.ProviderType; -import org.jetbrains.idea.svn.auth.SvnAuthenticationInteraction; -import org.jetbrains.idea.svn.auth.SvnAuthenticationListener; -import org.jetbrains.idea.svn.dialogs.SvnAuthenticationProvider; +import org.jetbrains.idea.svn.auth.*; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java index 1328b94fd7f0..6169f9415548 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java @@ -30,6 +30,8 @@ import com.intellij.util.Processor; import com.intellij.util.containers.Convertor; import junit.framework.Assert; import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; +import org.jetbrains.idea.svn.auth.SvnAuthenticationNotifier; import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider; import org.junit.Before; import org.tmatesoft.svn.core.*; diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnProtocolsTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnProtocolsTest.java index 69e3b510f4b4..6c9be603e362 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnProtocolsTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnProtocolsTest.java @@ -35,6 +35,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Processor; import com.intellij.util.containers.Convertor; import junit.framework.Assert; +import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider; import org.junit.Before; import org.tmatesoft.svn.core.*; diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnTestInteractiveAuthentication.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnTestInteractiveAuthentication.java index c12cfbb055c1..3b4b827a30a3 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnTestInteractiveAuthentication.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnTestInteractiveAuthentication.java @@ -17,6 +17,7 @@ package org.jetbrains.idea.svn; import com.intellij.util.containers.Convertor; import org.jetbrains.idea.svn.auth.ProviderType; +import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.*; diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java index 9652a1f25c8a..e8068989374b 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java @@ -24,14 +24,14 @@ import com.intellij.testFramework.PlatformTestCase; import com.intellij.util.concurrency.Semaphore; import com.intellij.util.ui.UIUtil; import junit.framework.Assert; -import org.jetbrains.idea.svn.SvnAuthenticationManager; -import org.jetbrains.idea.svn.SvnAuthenticationNotifier; +import org.jetbrains.idea.svn.auth.SvnAuthenticationManager; +import org.jetbrains.idea.svn.auth.SvnAuthenticationNotifier; import org.jetbrains.idea.svn.SvnConfiguration; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.auth.ProviderType; import org.jetbrains.idea.svn.auth.SvnAuthenticationInteraction; import org.jetbrains.idea.svn.auth.SvnAuthenticationListener; -import org.jetbrains.idea.svn.dialogs.SvnAuthenticationProvider; +import org.jetbrains.idea.svn.auth.SvnAuthenticationProvider; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; From 3b7d2e9bbe513d1ffc8f08bcd0164867fbd11108 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 30 Apr 2014 21:49:31 +0400 Subject: [PATCH 65/65] svn: Refactored IdeaSvnkitBasedAuthenticationCallback - inner classes moved to separate files --- .../idea/svn/auth/AbstractAuthenticator.java | 179 +++++++++ .../svn/auth/CredentialsAuthenticator.java | 115 ++++++ ...IdeaSvnkitBasedAuthenticationCallback.java | 372 +----------------- .../SSLServerCertificateAuthenticator.java | 168 ++++++++ 4 files changed, 463 insertions(+), 371 deletions(-) create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AbstractAuthenticator.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CredentialsAuthenticator.java create mode 100644 plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SSLServerCertificateAuthenticator.java diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AbstractAuthenticator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AbstractAuthenticator.java new file mode 100644 index 000000000000..2183c0d3e948 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/AbstractAuthenticator.java @@ -0,0 +1,179 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.auth; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.MessageType; +import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; +import com.intellij.util.messages.MessageBusConnection; +import org.intellij.lang.annotations.MagicConstant; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.idea.svn.SvnConfiguration; +import org.jetbrains.idea.svn.SvnVcs; +import org.tmatesoft.svn.core.SVNErrorMessage; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.auth.*; +import org.tmatesoft.svn.core.wc.SVNRevision; + +import java.io.IOException; + +/** + * @author Konstantin Kolosovsky. + */ +abstract class AbstractAuthenticator { + + private static final Logger LOG = Logger.getInstance(AbstractAuthenticator.class); + + @NotNull protected final IdeaSvnkitBasedAuthenticationCallback myAuthService; + @NotNull protected final SvnVcs myVcs; + @NotNull protected final SVNURL myUrl; + protected final String myRealm; + protected boolean myStoreInUsual; + protected SvnAuthenticationManager myTmpDirManager; + + AbstractAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, @NotNull SVNURL url, String realm) { + myAuthService = authService; + myVcs = myAuthService.getVcs(); + myUrl = url; + myRealm = realm; + } + + protected boolean tryAuthenticate() { + final SvnAuthenticationManager passive = myVcs.getSvnConfiguration().getPassiveAuthenticationManager(myVcs.getProject()); + final SvnAuthenticationManager active = myVcs.getSvnConfiguration().getAuthenticationManager(myVcs); + + try { + boolean authenticated = getWithPassive(passive) || getWithActive(active); + if (!authenticated) return false; + + SvnAuthenticationManager manager = myStoreInUsual ? active : createTmpManager(); + manager.setArtificialSaving(true); + return acknowledge(manager); + } + catch (IOException e) { + LOG.info(e); + VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), e.getMessage(), MessageType.ERROR); + return false; + } + catch (SVNException e) { + LOG.info(e); + VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), e.getMessage(), MessageType.ERROR); + return false; + } + } + + @NotNull + protected SvnAuthenticationManager createTmpManager() throws IOException { + if (myTmpDirManager == null) { + myAuthService.initTmpDir(myVcs.getSvnConfiguration()); + myTmpDirManager = new SvnAuthenticationManager(myVcs.getProject(), myAuthService.getTempDirectory()); + myTmpDirManager.setRuntimeStorage(SvnConfiguration.RUNTIME_AUTH_CACHE); + myTmpDirManager.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(myVcs, myTmpDirManager)); + } + + return myTmpDirManager; + } + + protected boolean getWithActive(SvnAuthenticationManager active) throws SVNException { + MessageBusConnection connection = null; + try { + final Project project = myVcs.getProject(); + connection = project.getMessageBus().connect(project); + connection.subscribe(SvnAuthenticationManager.AUTHENTICATION_PROVIDER_LISTENER, new MyAuthenticationProviderListener()); + + makeAuthCall(active); + } + finally { + if (connection != null) { + connection.disconnect(); + } + } + + return afterAuthCall(); + } + + protected void makeAuthCall(@NotNull SvnAuthenticationManager manager) throws SVNException { + myVcs.createWCClient(manager).doInfo(myUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD); + } + + protected void acceptServerAuthentication(SVNURL url, String realm, Object certificate, @MagicConstant int acceptResult) { + } + + public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) { + } + + protected abstract boolean afterAuthCall(); + + protected abstract boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException; + + protected abstract boolean acknowledge(SvnAuthenticationManager manager) throws SVNException; + + private class MyAuthenticationProviderListener implements SvnAuthenticationManager.ISVNAuthenticationProviderListener { + @Override + public void requestClientAuthentication(String kind, + SVNURL url, + String realm, + SVNErrorMessage errorMessage, + SVNAuthentication previousAuth, + boolean authMayBeStored, + SVNAuthentication authentication) { + AbstractAuthenticator.this.requestClientAuthentication(url, realm, authentication); + } + + @Override + public void acceptServerAuthentication(SVNURL url, + String realm, + Object certificate, + boolean resultMayBeStored, + @MagicConstant int acceptResult) { + AbstractAuthenticator.this.acceptServerAuthentication(url, realm, certificate, acceptResult); + } + } + + protected static boolean storeCredentials(@NotNull SvnAuthenticationManager manager, final SVNAuthentication authentication, String realm) + throws SVNException { + try { + if (authentication instanceof SVNSSLAuthentication && (((SVNSSLAuthentication)authentication).getCertificateFile() != null)) { + manager.acknowledgeForSSL(true, authentication); + realm = ((SVNSSLAuthentication)authentication).getCertificateFile().getPath(); + } + manager.acknowledgeAuthentication(true, getFromType(authentication), realm, null, authentication, authentication.getURL()); + } + catch (SvnAuthenticationManager.CredentialsSavedException e) { + return e.isSuccess(); + } + return true; + } + + @NotNull + private static String getFromType(SVNAuthentication authentication) { + if (authentication instanceof SVNPasswordAuthentication) { + return ISVNAuthenticationManager.PASSWORD; + } + if (authentication instanceof SVNSSHAuthentication) { + return ISVNAuthenticationManager.SSH; + } + if (authentication instanceof SVNSSLAuthentication) { + return ISVNAuthenticationManager.SSL; + } + if (authentication instanceof SVNUserNameAuthentication) { + return ISVNAuthenticationManager.USERNAME; + } + throw new IllegalArgumentException(); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CredentialsAuthenticator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CredentialsAuthenticator.java new file mode 100644 index 000000000000..410cb0997201 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/CredentialsAuthenticator.java @@ -0,0 +1,115 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.auth; + +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.tmatesoft.svn.core.SVNCancelException; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNURL; +import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; +import org.tmatesoft.svn.core.auth.SVNAuthentication; +import org.tmatesoft.svn.core.auth.SVNPasswordAuthentication; +import org.tmatesoft.svn.core.auth.SVNSSLAuthentication; + +import java.util.List; + +/** + * @author Konstantin Kolosovsky. + */ +class CredentialsAuthenticator extends AbstractAuthenticator { + private String myKind; + // sometimes realm string is different (with <>), so store credentials for both strings.. + private String myRealm2; + private SVNAuthentication myAuthentication; + + CredentialsAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, + @NotNull SVNURL url, + @Nullable String realm) { + super(authService, url, realm == null ? url.getHost() : realm); + } + + public boolean tryAuthenticate(boolean passwordRequest) { + final List kinds = IdeaSvnkitBasedAuthenticationCallback.getKinds(myUrl, passwordRequest); + for (String kind : kinds) { + myKind = kind; + if (!tryAuthenticate()) { + return false; + } + } + return true; + } + + @Override + protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException { + myAuthentication = getWithPassiveImpl(passive); + if (myAuthentication != null && !checkAuthOk(myAuthentication)) { + myAuthService.clearPassiveCredentials(myRealm, myUrl, + myAuthentication instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath + myAuthentication = null; + } + return myAuthentication != null; + } + + private SVNAuthentication getWithPassiveImpl(SvnAuthenticationManager passive) throws SVNException { + try { + return passive.getFirstAuthentication(myKind, myRealm, myUrl); + } + catch (SVNCancelException e) { + return null; + } + } + + private boolean checkAuthOk(SVNAuthentication authentication) { + if (authentication instanceof SVNPasswordAuthentication && StringUtil.isEmptyOrSpaces(authentication.getUserName())) return false; + if (authentication instanceof SVNSSLAuthentication) { + if (StringUtil.isEmptyOrSpaces(((SVNSSLAuthentication)authentication).getPassword())) return false; + } + return true; + } + + @Override + protected boolean getWithActive(final SvnAuthenticationManager active) throws SVNException { + if (ISVNAuthenticationManager.SSL.equals(myKind)) { + if (super.getWithActive(active)) return true; + } + myAuthentication = active.getProvider().requestClientAuthentication(myKind, myUrl, myRealm, null, null, true); + myStoreInUsual = myAuthService.getTempDirectory() == null && myAuthentication != null && myAuthentication.isStorageAllowed(); + + return myAuthentication != null; + } + + public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) { + if (!myUrl.equals(url)) return; + myAuthentication = authentication; + myRealm2 = realm; + myStoreInUsual = myAuthentication != null && myAuthentication.isStorageAllowed(); + } + + @Override + protected boolean afterAuthCall() { + return myAuthentication != null; + } + + @Override + protected boolean acknowledge(SvnAuthenticationManager manager) throws SVNException { + if (!StringUtil.isEmptyOrSpaces(myRealm2) && !myRealm2.equals(myRealm)) { + storeCredentials(manager, myAuthentication, myRealm2); + } + return storeCredentials(manager, myAuthentication, myRealm); + } +} diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/IdeaSvnkitBasedAuthenticationCallback.java index feed4915ff5e..d3551209ed0c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/IdeaSvnkitBasedAuthenticationCallback.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/IdeaSvnkitBasedAuthenticationCallback.java @@ -17,21 +17,16 @@ package org.jetbrains.idea.svn.auth; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.popup.util.PopupUtil; import com.intellij.openapi.util.Getter; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.util.WaitForProgressToShow; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.proxy.CommonProxy; -import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnBundle; @@ -41,18 +36,10 @@ import org.jetbrains.idea.svn.commandLine.AuthenticationCallback; import org.jetbrains.idea.svn.dialogs.SimpleCredentialsDialog; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.auth.*; -import org.tmatesoft.svn.core.internal.util.SVNBase64; -import org.tmatesoft.svn.core.internal.util.SVNHashMap; -import org.tmatesoft.svn.core.internal.util.SVNSSLUtil; -import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; -import org.tmatesoft.svn.core.internal.wc.SVNWCProperties; -import org.tmatesoft.svn.core.wc.SVNRevision; -import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.net.*; -import java.security.cert.*; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -290,348 +277,8 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall } } - private static abstract class AbstractAuthenticator { - @NotNull protected final IdeaSvnkitBasedAuthenticationCallback myAuthService; - @NotNull protected final SvnVcs myVcs; - @NotNull protected final SVNURL myUrl; - protected final String myRealm; - protected boolean myStoreInUsual; - protected SvnAuthenticationManager myTmpDirManager; - - protected AbstractAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, @NotNull SVNURL url, String realm) { - myAuthService = authService; - myVcs = myAuthService.getVcs(); - myUrl = url; - myRealm = realm; - } - - protected boolean tryAuthenticate() { - final SvnAuthenticationManager passive = myVcs.getSvnConfiguration().getPassiveAuthenticationManager(myVcs.getProject()); - final SvnAuthenticationManager active = myVcs.getSvnConfiguration().getAuthenticationManager(myVcs); - - try { - boolean authenticated = getWithPassive(passive) || getWithActive(active); - if (!authenticated) return false; - - SvnAuthenticationManager manager = myStoreInUsual ? active : createTmpManager(); - manager.setArtificialSaving(true); - return acknowledge(manager); - } - catch (IOException e) { - LOG.info(e); - VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), e.getMessage(), MessageType.ERROR); - return false; - } - catch (SVNException e) { - LOG.info(e); - VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), e.getMessage(), MessageType.ERROR); - return false; - } - } - - @NotNull - protected SvnAuthenticationManager createTmpManager() throws IOException { - if (myTmpDirManager == null) { - myAuthService.initTmpDir(myVcs.getSvnConfiguration()); - myTmpDirManager = new SvnAuthenticationManager(myVcs.getProject(), myAuthService.getTempDirectory()); - myTmpDirManager.setRuntimeStorage(SvnConfiguration.RUNTIME_AUTH_CACHE); - myTmpDirManager.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(myVcs, myTmpDirManager)); - } - - return myTmpDirManager; - } - - protected boolean getWithActive(SvnAuthenticationManager active) throws SVNException { - MessageBusConnection connection = null; - try { - final Project project = myVcs.getProject(); - connection = project.getMessageBus().connect(project); - connection.subscribe(SvnAuthenticationManager.AUTHENTICATION_PROVIDER_LISTENER, new MyAuthenticationProviderListener()); - - makeAuthCall(active); - } - finally { - if (connection != null) { - connection.disconnect(); - } - } - - return afterAuthCall(); - } - - protected void makeAuthCall(@NotNull SvnAuthenticationManager manager) throws SVNException { - myVcs.createWCClient(manager).doInfo(myUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD); - } - - protected void acceptServerAuthentication(SVNURL url, String realm, Object certificate, @MagicConstant int acceptResult) { - } - - public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) { - } - - protected abstract boolean afterAuthCall(); - - protected abstract boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException; - - protected abstract boolean acknowledge(SvnAuthenticationManager manager) throws SVNException; - - private class MyAuthenticationProviderListener implements SvnAuthenticationManager.ISVNAuthenticationProviderListener { - @Override - public void requestClientAuthentication(String kind, - SVNURL url, - String realm, - SVNErrorMessage errorMessage, - SVNAuthentication previousAuth, - boolean authMayBeStored, - SVNAuthentication authentication) { - AbstractAuthenticator.this.requestClientAuthentication(url, realm, authentication); - } - - @Override - public void acceptServerAuthentication(SVNURL url, - String realm, - Object certificate, - boolean resultMayBeStored, - @MagicConstant int acceptResult) { - AbstractAuthenticator.this.acceptServerAuthentication(url, realm, certificate, acceptResult); - } - } - } - - // plus seems that we also should ask for credentials; but we didn't receive realm name yet - private static class SSLServerCertificateAuthenticator extends AbstractAuthenticator { - private String myCertificateRealm; - private String myCredentialsRealm; - private Object myCertificate; - private int myResult; - private SVNAuthentication myAuthentication; - - protected SSLServerCertificateAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, - @NotNull SVNURL url, - String realm) { - super(authService, url, realm); - } - - @Override - public boolean tryAuthenticate() { - myResult = ISVNAuthenticationProvider.ACCEPTED_TEMPORARY; - myStoreInUsual = false; - return super.tryAuthenticate(); - } - - @Override - protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException { - String stored = (String)passive.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm); - if (stored == null) return false; - - myCertificate = createCertificate(stored); - myCertificateRealm = myRealm; - return true; - } - - @Override - public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) { - if (!myUrl.equals(url)) return; - myCredentialsRealm = realm; - myAuthentication = authentication; - if (myAuthentication != null) { - myStoreInUsual &= myAuthentication.isStorageAllowed(); - } - } - - @Override - public void acceptServerAuthentication(SVNURL url, String realm, Object certificate, @MagicConstant int acceptResult) { - if (!myUrl.equals(url)) return; - myCertificateRealm = realm; - myCertificate = certificate; - myResult = acceptResult; - } - - @Override - protected boolean afterAuthCall() { - myStoreInUsual &= myCertificate != null && ISVNAuthenticationProvider.ACCEPTED == myResult; - // TODO: Previous code always returned not null value, so Boolean == null check was always false in tryAuthenticate(). - // TODO: This was most likely error in code - check once again. - return ISVNAuthenticationProvider.REJECTED != myResult && myCertificate != null; - } - - @Override - protected boolean acknowledge(SvnAuthenticationManager manager) throws SVNException { - // we should store certificate, if it wasn't accepted (if temporally tmp) - if (myCertificate == null) { // this is if certificate was stored only in passive area - String stored = (String)manager.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm); - if (StringUtil.isEmptyOrSpaces(stored)) { - throw new SVNException( - SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, "No stored server certificate was found in runtime")); - } - myCertificate = createCertificate(stored); - myCertificateRealm = myRealm; - } - if (myAuthService.getTempDirectory() != null && myCertificate != null) { - storeServerCertificate(); - - if (myAuthentication != null) { - final String realm = myCredentialsRealm == null ? myCertificateRealm : myCredentialsRealm; - return storeCredentials(manager, myAuthentication, realm); - } - } - return true; - } - - @NotNull - private Certificate createCertificate(@NotNull String stored) throws SVNException { - CertificateFactory factory; - try { - factory = CertificateFactory.getInstance("X509"); - final byte[] buffer = new byte[stored.length()]; - SVNBase64.base64ToByteArray(new StringBuffer(stored), buffer); - - return factory.generateCertificate(new ByteArrayInputStream(buffer)); - } - catch (CertificateException e) { - throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, e)); - } - } - - private void storeServerCertificate() throws SVNException { - if (!(myCertificate instanceof X509Certificate)) { - throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, "Can not store server certificate: " + myCertificate)); - } - X509Certificate x509Certificate = (X509Certificate)myCertificate; - String stored; - try { - stored = SVNBase64.byteArrayToBase64(x509Certificate.getEncoded()); - } - catch (CertificateEncodingException e) { - throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e)); - } - - int failures = SVNSSLUtil.getServerCertificateFailures(x509Certificate, myUrl.getHost()); - storeServerCertificate(myAuthService.getTempDirectory(), myCertificateRealm, stored, failures); - } - - private void storeServerCertificate(final File configDir, String realm, String data, int failures) throws SVNException { - //noinspection ResultOfMethodCallIgnored - configDir.mkdirs(); - - File file = new File(configDir, "auth/svn.ssl.server/" + SVNFileUtil.computeChecksum(realm)); - SVNHashMap map = new SVNHashMap(); - map.put("ascii_cert", data); - map.put("svn:realmstring", realm); - map.put("failures", Integer.toString(failures)); - - SVNFileUtil.deleteFile(file); - - File tmpFile = SVNFileUtil.createUniqueFile(configDir, "auth", ".tmp", true); - try { - SVNWCProperties.setProperties(SVNProperties.wrap(map), file, tmpFile, SVNWCProperties.SVN_HASH_TERMINATOR); - } - finally { - SVNFileUtil.deleteFile(tmpFile); - } - } - } - - private static boolean storeCredentials(@NotNull SvnAuthenticationManager manager, final SVNAuthentication authentication, String realm) - throws SVNException { - try { - if (authentication instanceof SVNSSLAuthentication && (((SVNSSLAuthentication)authentication).getCertificateFile() != null)) { - manager.acknowledgeForSSL(true, authentication); - realm = ((SVNSSLAuthentication)authentication).getCertificateFile().getPath(); - } - manager.acknowledgeAuthentication(true, getFromType(authentication), realm, null, authentication, authentication.getURL()); - } - catch (SvnAuthenticationManager.CredentialsSavedException e) { - return e.isSuccess(); - } - return true; - } - - private static class CredentialsAuthenticator extends AbstractAuthenticator { - private String myKind; - // sometimes realm string is different (with <>), so store credentials for both strings.. - private String myRealm2; - private SVNAuthentication myAuthentication; - - protected CredentialsAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, - @NotNull SVNURL url, - @Nullable String realm) { - super(authService, url, realm == null ? url.getHost() : realm); - } - - public boolean tryAuthenticate(boolean passwordRequest) { - final List kinds = getKinds(myUrl, passwordRequest); - for (String kind : kinds) { - myKind = kind; - if (!tryAuthenticate()) { - return false; - } - } - return true; - } - - @Override - protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException { - myAuthentication = getWithPassiveImpl(passive); - if (myAuthentication != null && !checkAuthOk(myAuthentication)) { - myAuthService.clearPassiveCredentials(myRealm, myUrl, - myAuthentication instanceof SVNPasswordAuthentication); //clear passive also take into acconut ssl filepath - myAuthentication = null; - } - return myAuthentication != null; - } - - private SVNAuthentication getWithPassiveImpl(SvnAuthenticationManager passive) throws SVNException { - try { - return passive.getFirstAuthentication(myKind, myRealm, myUrl); - } - catch (SVNCancelException e) { - return null; - } - } - - private boolean checkAuthOk(SVNAuthentication authentication) { - if (authentication instanceof SVNPasswordAuthentication && StringUtil.isEmptyOrSpaces(authentication.getUserName())) return false; - if (authentication instanceof SVNSSLAuthentication) { - if (StringUtil.isEmptyOrSpaces(((SVNSSLAuthentication)authentication).getPassword())) return false; - } - return true; - } - - @Override - protected boolean getWithActive(final SvnAuthenticationManager active) throws SVNException { - if (ISVNAuthenticationManager.SSL.equals(myKind)) { - if (super.getWithActive(active)) return true; - } - myAuthentication = active.getProvider().requestClientAuthentication(myKind, myUrl, myRealm, null, null, true); - myStoreInUsual = myAuthService.getTempDirectory() == null && myAuthentication != null && myAuthentication.isStorageAllowed(); - - return myAuthentication != null; - } - - public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) { - if (!myUrl.equals(url)) return; - myAuthentication = authentication; - myRealm2 = realm; - myStoreInUsual = myAuthentication != null && myAuthentication.isStorageAllowed(); - } - - @Override - protected boolean afterAuthCall() { - return myAuthentication != null; - } - - @Override - protected boolean acknowledge(SvnAuthenticationManager manager) throws SVNException { - if (!StringUtil.isEmptyOrSpaces(myRealm2) && !myRealm2.equals(myRealm)) { - storeCredentials(manager, myAuthentication, myRealm2); - } - return storeCredentials(manager, myAuthentication, myRealm); - } - } - @NotNull - private static List getKinds(final SVNURL url, boolean passwordRequest) { + public static List getKinds(final SVNURL url, boolean passwordRequest) { if (passwordRequest || "http".equals(url.getProtocol())) { return Collections.singletonList(ISVNAuthenticationManager.PASSWORD); } @@ -659,21 +306,4 @@ public class IdeaSvnkitBasedAuthenticationCallback implements AuthenticationCall FileUtil.copyDir(new File(configuration.getConfigurationDirectory()), myTempDirectory); } } - - @NotNull - private static String getFromType(SVNAuthentication authentication) { - if (authentication instanceof SVNPasswordAuthentication) { - return ISVNAuthenticationManager.PASSWORD; - } - if (authentication instanceof SVNSSHAuthentication) { - return ISVNAuthenticationManager.SSH; - } - if (authentication instanceof SVNSSLAuthentication) { - return ISVNAuthenticationManager.SSL; - } - if (authentication instanceof SVNUserNameAuthentication) { - return ISVNAuthenticationManager.USERNAME; - } - throw new IllegalArgumentException(); - } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SSLServerCertificateAuthenticator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SSLServerCertificateAuthenticator.java new file mode 100644 index 000000000000..3b78aa55d867 --- /dev/null +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/auth/SSLServerCertificateAuthenticator.java @@ -0,0 +1,168 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.idea.svn.auth; + +import com.intellij.openapi.util.text.StringUtil; +import org.intellij.lang.annotations.MagicConstant; +import org.jetbrains.annotations.NotNull; +import org.tmatesoft.svn.core.*; +import org.tmatesoft.svn.core.auth.ISVNAuthenticationProvider; +import org.tmatesoft.svn.core.auth.SVNAuthentication; +import org.tmatesoft.svn.core.internal.util.SVNBase64; +import org.tmatesoft.svn.core.internal.util.SVNHashMap; +import org.tmatesoft.svn.core.internal.util.SVNSSLUtil; +import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; +import org.tmatesoft.svn.core.internal.wc.SVNWCProperties; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.security.cert.*; + +/** +* @author Konstantin Kolosovsky. +*/ // plus seems that we also should ask for credentials; but we didn't receive realm name yet +class SSLServerCertificateAuthenticator extends AbstractAuthenticator { + private String myCertificateRealm; + private String myCredentialsRealm; + private Object myCertificate; + private int myResult; + private SVNAuthentication myAuthentication; + + SSLServerCertificateAuthenticator(@NotNull IdeaSvnkitBasedAuthenticationCallback authService, + @NotNull SVNURL url, + String realm) { + super(authService, url, realm); + } + + @Override + public boolean tryAuthenticate() { + myResult = ISVNAuthenticationProvider.ACCEPTED_TEMPORARY; + myStoreInUsual = false; + return super.tryAuthenticate(); + } + + @Override + protected boolean getWithPassive(SvnAuthenticationManager passive) throws SVNException { + String stored = (String)passive.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm); + if (stored == null) return false; + + myCertificate = createCertificate(stored); + myCertificateRealm = myRealm; + return true; + } + + @Override + public void requestClientAuthentication(SVNURL url, String realm, SVNAuthentication authentication) { + if (!myUrl.equals(url)) return; + myCredentialsRealm = realm; + myAuthentication = authentication; + if (myAuthentication != null) { + myStoreInUsual &= myAuthentication.isStorageAllowed(); + } + } + + @Override + public void acceptServerAuthentication(SVNURL url, String realm, Object certificate, @MagicConstant int acceptResult) { + if (!myUrl.equals(url)) return; + myCertificateRealm = realm; + myCertificate = certificate; + myResult = acceptResult; + } + + @Override + protected boolean afterAuthCall() { + myStoreInUsual &= myCertificate != null && ISVNAuthenticationProvider.ACCEPTED == myResult; + // TODO: Previous code always returned not null value, so Boolean == null check was always false in tryAuthenticate(). + // TODO: This was most likely error in code - check once again. + return ISVNAuthenticationProvider.REJECTED != myResult && myCertificate != null; + } + + @Override + protected boolean acknowledge(SvnAuthenticationManager manager) throws SVNException { + // we should store certificate, if it wasn't accepted (if temporally tmp) + if (myCertificate == null) { // this is if certificate was stored only in passive area + String stored = (String)manager.getRuntimeAuthStorage().getData("svn.ssl.server", myRealm); + if (StringUtil.isEmptyOrSpaces(stored)) { + throw new SVNException( + SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, "No stored server certificate was found in runtime")); + } + myCertificate = createCertificate(stored); + myCertificateRealm = myRealm; + } + if (myAuthService.getTempDirectory() != null && myCertificate != null) { + storeServerCertificate(); + + if (myAuthentication != null) { + final String realm = myCredentialsRealm == null ? myCertificateRealm : myCredentialsRealm; + return storeCredentials(manager, myAuthentication, realm); + } + } + return true; + } + + @NotNull + private Certificate createCertificate(@NotNull String stored) throws SVNException { + CertificateFactory factory; + try { + factory = CertificateFactory.getInstance("X509"); + final byte[] buffer = new byte[stored.length()]; + SVNBase64.base64ToByteArray(new StringBuffer(stored), buffer); + + return factory.generateCertificate(new ByteArrayInputStream(buffer)); + } + catch (CertificateException e) { + throw new SVNException(SVNErrorMessage.create(SVNErrorCode.AUTHN_CREDS_UNAVAILABLE, e)); + } + } + + private void storeServerCertificate() throws SVNException { + if (!(myCertificate instanceof X509Certificate)) { + throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, "Can not store server certificate: " + myCertificate)); + } + X509Certificate x509Certificate = (X509Certificate)myCertificate; + String stored; + try { + stored = SVNBase64.byteArrayToBase64(x509Certificate.getEncoded()); + } + catch (CertificateEncodingException e) { + throw new SVNException(SVNErrorMessage.create(SVNErrorCode.IO_ERROR, e)); + } + + int failures = SVNSSLUtil.getServerCertificateFailures(x509Certificate, myUrl.getHost()); + storeServerCertificate(myAuthService.getTempDirectory(), myCertificateRealm, stored, failures); + } + + private void storeServerCertificate(final File configDir, String realm, String data, int failures) throws SVNException { + //noinspection ResultOfMethodCallIgnored + configDir.mkdirs(); + + File file = new File(configDir, "auth/svn.ssl.server/" + SVNFileUtil.computeChecksum(realm)); + SVNHashMap map = new SVNHashMap(); + map.put("ascii_cert", data); + map.put("svn:realmstring", realm); + map.put("failures", Integer.toString(failures)); + + SVNFileUtil.deleteFile(file); + + File tmpFile = SVNFileUtil.createUniqueFile(configDir, "auth", ".tmp", true); + try { + SVNWCProperties.setProperties(SVNProperties.wrap(map), file, tmpFile, SVNWCProperties.SVN_HASH_TERMINATOR); + } + finally { + SVNFileUtil.deleteFile(tmpFile); + } + } +}