package org.tmatesoft.svn.test; import org.junit.Assert; import org.junit.Assume; import org.junit.Ignore; import org.junit.Test; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.auth.BasicAuthenticationManager; import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions; import org.tmatesoft.svn.core.internal.wc.SVNExternal; import org.tmatesoft.svn.core.internal.wc.SVNFileListUtil; import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; import org.tmatesoft.svn.core.internal.wc17.SVNWCContext; import org.tmatesoft.svn.core.internal.wc17.db.statement.SVNWCDbSchema; import org.tmatesoft.svn.core.internal.wc2.compat.SvnCodec; import org.tmatesoft.svn.core.wc.*; import org.tmatesoft.svn.core.wc2.*; import java.io.File; import java.util.*; public class MergeTest { @Ignore("Temporarily ignored") @Test public void testConflictResolution() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testConflictResolution", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.addFile("file", "base".getBytes()); SVNCommitInfo commitInfo1 = commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.changeFile("file", "theirs".getBytes()); commitBuilder2.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url, commitInfo1.getNewRevision()); final File workingCopyDirectory = workingCopy.getWorkingCopyDirectory(); final File file = new File(workingCopyDirectory, "file"); TestUtil.writeFileContentsString(file, "mine"); final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); runResolve(svnOperationFactory, file, SVNConflictChoice.MINE_CONFLICT); final String fileContentsString = TestUtil.readFileContentsString(file); Assert.assertEquals("mine", fileContentsString); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testRemoteAddOverUnversionedFileConflictResolution() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testRemoteAddOverUnversionedFileConflictResolution", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.addFile("file", "their".getBytes()); commitBuilder2.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url, 1); final File workingCopyDirectory = workingCopy.getWorkingCopyDirectory(); final File file = workingCopy.getFile("file"); SVNFileUtil.ensureDirectoryExists(file.getParentFile()); TestUtil.writeFileContentsString(file, "mine"); boolean isExceptionExpected = !TestUtil.isNewWorkingCopyTest(); if (isExceptionExpected) { final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); try { update.run(); Assert.fail("An exception should be thrown"); } catch (SVNException e) { //expected for WC 1.6 Assert.assertEquals(SVNErrorCode.WC_OBSTRUCTED_UPDATE, e.getErrorMessage().getErrorCode()); } } else { final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); runResolve(svnOperationFactory, file, SVNConflictChoice.MERGED); Assert.assertEquals("mine", TestUtil.readFileContentsString(file)); final Map<File, SvnStatus> statuses = TestUtil.getStatuses(svnOperationFactory, workingCopyDirectory); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(file).getNodeStatus()); Assert.assertFalse(statuses.get(file).isConflicted()); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testBothDeletedTreeConflict() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testBothDeletedTreeConflict", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.addFile("file"); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.delete("file"); commitBuilder2.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url, 1); final File file = workingCopy.getFile("file"); workingCopy.delete(file); update(svnOperationFactory, workingCopy); final SvnGetInfo getInfo = svnOperationFactory.createGetInfo(); getInfo.setSingleTarget(SvnTarget.fromFile(file)); final SvnInfo svnInfo = getInfo.run(); final Collection<SVNConflictDescription> conflicts = svnInfo.getWcInfo().getConflicts(); Assert.assertEquals(1, conflicts.size()); final SVNTreeConflictDescription conflict = (SVNTreeConflictDescription) conflicts.iterator().next(); Assert.assertEquals(SVNConflictAction.DELETE, conflict.getConflictAction()); Assert.assertEquals(SVNConflictReason.DELETED, conflict.getConflictReason()); Assert.assertEquals(url, conflict.getSourceLeftVersion().getRepositoryRoot()); Assert.assertEquals(url, conflict.getSourceRightVersion().getRepositoryRoot()); final SvnSchedule schedule = svnInfo.getWcInfo().getSchedule(); Assert.assertEquals(SvnSchedule.NORMAL, schedule); final Map<File, SvnStatus> statuses = TestUtil.getStatuses(svnOperationFactory, workingCopy.getWorkingCopyDirectory()); final SvnStatus fileStatus = statuses.get(file); Assert.assertTrue(fileStatus.isConflicted()); Assert.assertEquals(SVNStatusType.STATUS_CONFLICTED, fileStatus.getNodeStatus()); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testUpdateDeletedLockedFileDoesntCauseTreeConflictDavAccess() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllApacheOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testUpdateDeletedLockedFileDoesntCauseTreeConflictDavAccess", options); try { final BasicAuthenticationManager authenticationManager = new BasicAuthenticationManager("user", "password"); svnOperationFactory.setAuthenticationManager(authenticationManager); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user", "password"); final SVNURL url = sandbox.createSvnRepositoryWithDavAccess(loginToPassword); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.setAuthenticationManager(authenticationManager); commitBuilder.addFile("directory/file"); commitBuilder.commit(); final File workingCopyDirectory = sandbox.createDirectory("wc"); final File file = new File(workingCopyDirectory, "directory/file"); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final SvnScheduleForRemoval scheduleForRemoval = svnOperationFactory.createScheduleForRemoval(); scheduleForRemoval.setSingleTarget(SvnTarget.fromFile(file)); scheduleForRemoval.run(); final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); final Map<File, SvnStatus> statuses = TestUtil.getStatuses(svnOperationFactory, workingCopyDirectory); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(file).getNodeStatus()); Assert.assertNotNull(statuses.get(file).getLock()); final SVNWCContext context = new SVNWCContext(svnOperationFactory.getOptions(), svnOperationFactory.getEventHandler()); try { final SVNStatus oldStatus = SvnCodec.status(context, statuses.get(file)); Assert.assertNull(oldStatus.getTreeConflict()); } finally { context.close(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testUpdateDeletedLockedFileDoesntCauseTreeConflictSvnAccess() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllSvnserveOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testUpdateDeletedLockedFileDoesntCauseTreeConflictSvnAccess", options); try { final BasicAuthenticationManager authenticationManager = new BasicAuthenticationManager("user", "password"); svnOperationFactory.setAuthenticationManager(authenticationManager); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user", "password"); final SVNURL url = sandbox.createSvnRepositoryWithSvnAccess(loginToPassword); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.setAuthenticationManager(authenticationManager); commitBuilder.addFile("directory/file"); commitBuilder.commit(); final File workingCopyDirectory = sandbox.createDirectory("wc"); final File file = new File(workingCopyDirectory, "directory/file"); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final SvnScheduleForRemoval scheduleForRemoval = svnOperationFactory.createScheduleForRemoval(); scheduleForRemoval.setSingleTarget(SvnTarget.fromFile(file)); scheduleForRemoval.run(); final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); final Map<File, SvnStatus> statuses = TestUtil.getStatuses(svnOperationFactory, workingCopyDirectory); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(file).getNodeStatus()); Assert.assertNotNull(statuses.get(file).getLock()); final SVNWCContext context = new SVNWCContext(svnOperationFactory.getOptions(), svnOperationFactory.getEventHandler()); try { final SVNStatus oldStatus = SvnCodec.status(context, statuses.get(file)); Assert.assertNull(oldStatus.getTreeConflict()); } finally { context.close(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testUpdateOnRenamedParentOfLockedFileDoesntCauseTreeConflictDavAccess() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllApacheOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testUpdateOnRenamedParentOfLockedFileDoesntCauseTreeConflictDavAccess", options); try { final BasicAuthenticationManager authenticationManager = new BasicAuthenticationManager("user", "password"); svnOperationFactory.setAuthenticationManager(authenticationManager); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user", "password"); final SVNURL url = sandbox.createSvnRepositoryWithDavAccess(loginToPassword); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.setAuthenticationManager(authenticationManager); commitBuilder.addFile("directory/file"); commitBuilder.commit(); final File workingCopyDirectory = sandbox.createDirectory("wc"); final File file = new File(workingCopyDirectory, "directory/file"); final File directory = new File(workingCopyDirectory, "directory"); final File renamedDirectory = new File(workingCopyDirectory, "renamedDirectory"); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); final SvnScheduleForRemoval scheduleForRemoval = svnOperationFactory.createScheduleForRemoval(); scheduleForRemoval.setSingleTarget(SvnTarget.fromFile(file)); scheduleForRemoval.run(); final SvnCopy copy = svnOperationFactory.createCopy(); copy.setMove(true); copy.addCopySource(SvnCopySource.create(SvnTarget.fromFile(directory), SVNRevision.WORKING)); copy.setSingleTarget(SvnTarget.fromFile(renamedDirectory)); copy.run(); final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); final Map<File, SvnStatus> statuses = TestUtil.getStatuses(svnOperationFactory, workingCopyDirectory); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(directory).getNodeStatus()); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(file).getNodeStatus()); Assert.assertNotNull(statuses.get(file).getLock()); final SVNWCContext context = new SVNWCContext(svnOperationFactory.getOptions(), svnOperationFactory.getEventHandler()); try { final SVNStatus oldDirectoryStatus = SvnCodec.status(context, statuses.get(directory)); Assert.assertNull(oldDirectoryStatus.getTreeConflict()); final SVNStatus oldFileStatus = SvnCodec.status(context, statuses.get(file)); Assert.assertNull(oldFileStatus.getTreeConflict()); } finally { context.close(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testUpdateOnRenamedParentOfLockedFileDoesntCauseTreeConflictSvnAccess() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllSvnserveOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testUpdateOnRenamedParentOfLockedFileDoesntCauseTreeConflictSvnAccess", options); try { final BasicAuthenticationManager authenticationManager = new BasicAuthenticationManager("user", "password"); svnOperationFactory.setAuthenticationManager(authenticationManager); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user", "password"); final SVNURL url = sandbox.createSvnRepositoryWithSvnAccess(loginToPassword); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.setAuthenticationManager(authenticationManager); commitBuilder.addFile("directory/file"); commitBuilder.commit(); final File workingCopyDirectory = sandbox.createDirectory("wc"); final File file = new File(workingCopyDirectory, "directory/file"); final File directory = new File(workingCopyDirectory, "directory"); final File renamedDirectory = new File(workingCopyDirectory, "renamedDirectory"); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); final SvnScheduleForRemoval scheduleForRemoval = svnOperationFactory.createScheduleForRemoval(); scheduleForRemoval.setSingleTarget(SvnTarget.fromFile(file)); scheduleForRemoval.run(); final SvnCopy copy = svnOperationFactory.createCopy(); copy.setMove(true); copy.addCopySource(SvnCopySource.create(SvnTarget.fromFile(directory), SVNRevision.WORKING)); copy.setSingleTarget(SvnTarget.fromFile(renamedDirectory)); copy.run(); final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); final Map<File, SvnStatus> statuses = TestUtil.getStatuses(svnOperationFactory, workingCopyDirectory); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(directory).getNodeStatus()); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(file).getNodeStatus()); Assert.assertNotNull(statuses.get(file).getLock()); final SVNWCContext context = new SVNWCContext(svnOperationFactory.getOptions(), svnOperationFactory.getEventHandler()); try { final SVNStatus oldDirectoryStatus = SvnCodec.status(context, statuses.get(directory)); Assert.assertNull(oldDirectoryStatus.getTreeConflict()); final SVNStatus oldFileStatus = SvnCodec.status(context, statuses.get(file)); Assert.assertNull(oldFileStatus.getTreeConflict()); } finally { context.close(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testUpdateOnRenamedParentOfLockedFileAnotherFileDeletedDavAccess() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllApacheOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testUpdateOnRenamedParentOfLockedFileAnotherFileDeletedDavAccess", options); try { final BasicAuthenticationManager authenticationManager = new BasicAuthenticationManager("user", "password"); svnOperationFactory.setAuthenticationManager(authenticationManager); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user", "password"); final SVNURL url = sandbox.createSvnRepositoryWithDavAccess(loginToPassword); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.setAuthenticationManager(authenticationManager); commitBuilder1.addFile("directory/file"); commitBuilder1.addFile("directory/fileToDelete"); commitBuilder1.addFile("fileToDelete"); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.setAuthenticationManager(authenticationManager); commitBuilder2.delete("directory/fileToDelete"); commitBuilder2.delete("fileToDelete"); commitBuilder2.commit(); final File workingCopyDirectory = sandbox.createDirectory("wc"); final File file = new File(workingCopyDirectory, "directory/file"); final File directory = new File(workingCopyDirectory, "directory"); final File renamedDirectory = new File(workingCopyDirectory, "renamedDirectory"); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); final SvnScheduleForRemoval scheduleForRemoval = svnOperationFactory.createScheduleForRemoval(); scheduleForRemoval.setSingleTarget(SvnTarget.fromFile(file)); scheduleForRemoval.run(); final SvnCopy copy = svnOperationFactory.createCopy(); copy.setMove(true); copy.addCopySource(SvnCopySource.create(SvnTarget.fromFile(directory), SVNRevision.WORKING)); copy.setSingleTarget(SvnTarget.fromFile(renamedDirectory)); copy.run(); final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); final Map<File, SvnStatus> statuses = TestUtil.getStatuses(svnOperationFactory, workingCopyDirectory); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(directory).getNodeStatus()); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(file).getNodeStatus()); Assert.assertNotNull(statuses.get(file).getLock()); final SVNWCContext context = new SVNWCContext(svnOperationFactory.getOptions(), svnOperationFactory.getEventHandler()); try { final SVNStatus oldDirectoryStatus = SvnCodec.status(context, statuses.get(directory)); Assert.assertNull(oldDirectoryStatus.getTreeConflict()); final SVNStatus oldFileStatus = SvnCodec.status(context, statuses.get(file)); Assert.assertNull(oldFileStatus.getTreeConflict()); } finally { context.close(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testUpdateOnRenamedParentOfLockedFileAnotherFileDeletedSvnAccess() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllSvnserveOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testUpdateOnRenamedParentOfLockedFileAnotherFileDeletedSvnAccess", options); try { final BasicAuthenticationManager authenticationManager = new BasicAuthenticationManager("user", "password"); svnOperationFactory.setAuthenticationManager(authenticationManager); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user", "password"); final SVNURL url = sandbox.createSvnRepositoryWithSvnAccess(loginToPassword); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.setAuthenticationManager(authenticationManager); commitBuilder1.addFile("directory/file"); commitBuilder1.addFile("directory/fileToDelete"); commitBuilder1.addFile("fileToDelete"); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.setAuthenticationManager(authenticationManager); commitBuilder2.delete("directory/fileToDelete"); commitBuilder2.delete("fileToDelete"); commitBuilder2.commit(); final File workingCopyDirectory = sandbox.createDirectory("wc"); final File file = new File(workingCopyDirectory, "directory/file"); final File directory = new File(workingCopyDirectory, "directory"); final File renamedDirectory = new File(workingCopyDirectory, "renamedDirectory"); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); final SvnScheduleForRemoval scheduleForRemoval = svnOperationFactory.createScheduleForRemoval(); scheduleForRemoval.setSingleTarget(SvnTarget.fromFile(file)); scheduleForRemoval.run(); final SvnCopy copy = svnOperationFactory.createCopy(); copy.setMove(true); copy.addCopySource(SvnCopySource.create(SvnTarget.fromFile(directory), SVNRevision.WORKING)); copy.setSingleTarget(SvnTarget.fromFile(renamedDirectory)); copy.run(); final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); final Map<File, SvnStatus> statuses = TestUtil.getStatuses(svnOperationFactory, workingCopyDirectory); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(directory).getNodeStatus()); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(file).getNodeStatus()); Assert.assertNotNull(statuses.get(file).getLock()); final SVNWCContext context = new SVNWCContext(svnOperationFactory.getOptions(), svnOperationFactory.getEventHandler()); try { final SVNStatus oldDirectoryStatus = SvnCodec.status(context, statuses.get(directory)); Assert.assertNull(oldDirectoryStatus.getTreeConflict()); final SVNStatus oldFileStatus = SvnCodec.status(context, statuses.get(file)); Assert.assertNull(oldFileStatus.getTreeConflict()); } finally { context.close(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testUpdateOnMovedParentOfLockedFileDoesntCauseTreeConflictDavAccess() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllApacheOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testUpdateOnRenamedParentOfLockedFileDoesntCauseTreeConflictDavAccess", options); try { final BasicAuthenticationManager authenticationManager = new BasicAuthenticationManager("user", "password"); svnOperationFactory.setAuthenticationManager(authenticationManager); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user", "password"); final SVNURL url = sandbox.createSvnRepositoryWithDavAccess(loginToPassword); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.setAuthenticationManager(authenticationManager); commitBuilder.addFile("directory/subdirectory/file"); commitBuilder.addDirectory("anotherDirectory"); commitBuilder.commit(); final File workingCopyDirectory = sandbox.createDirectory("wc"); final File directory = new File(workingCopyDirectory, "directory"); final File subdirectory = new File(directory, "subdirectory"); final File file = new File(subdirectory, "file"); final File anotherDirectory = new File(workingCopyDirectory, "anotherDirectory"); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); final SvnScheduleForRemoval scheduleForRemoval = svnOperationFactory.createScheduleForRemoval(); scheduleForRemoval.setSingleTarget(SvnTarget.fromFile(file)); scheduleForRemoval.run(); final SvnCopy copy = svnOperationFactory.createCopy(); copy.setFailWhenDstExists(false); copy.setMove(true); copy.addCopySource(SvnCopySource.create(SvnTarget.fromFile(subdirectory), SVNRevision.WORKING)); copy.setSingleTarget(SvnTarget.fromFile(anotherDirectory)); copy.run(); final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); final Map<File, SvnStatus> statuses = TestUtil.getStatuses(svnOperationFactory, workingCopyDirectory); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(subdirectory).getNodeStatus()); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(file).getNodeStatus()); Assert.assertNotNull(statuses.get(file).getLock()); final SVNWCContext context = new SVNWCContext(svnOperationFactory.getOptions(), svnOperationFactory.getEventHandler()); try { final SVNStatus oldDirectoryStatus = SvnCodec.status(context, statuses.get(subdirectory)); Assert.assertNull(oldDirectoryStatus.getTreeConflict()); final SVNStatus oldFileStatus = SvnCodec.status(context, statuses.get(file)); Assert.assertNull(oldFileStatus.getTreeConflict()); } finally { context.close(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testUpdateOnMovedParentOfLockedFileDoesntCauseTreeConflictSvnAccess() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.areAllSvnserveOptionsSpecified(options)); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testUpdateOnRenamedParentOfLockedFileDoesntCauseTreeConflictSvnAccess", options); try { final BasicAuthenticationManager authenticationManager = new BasicAuthenticationManager("user", "password"); svnOperationFactory.setAuthenticationManager(authenticationManager); final Map<String, String> loginToPassword = new HashMap<String, String>(); loginToPassword.put("user", "password"); final SVNURL url = sandbox.createSvnRepositoryWithSvnAccess(loginToPassword); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.setAuthenticationManager(authenticationManager); commitBuilder.addFile("directory/subdirectory/file"); commitBuilder.addDirectory("anotherDirectory"); commitBuilder.commit(); final File workingCopyDirectory = sandbox.createDirectory("wc"); final File directory = new File(workingCopyDirectory, "directory"); final File subdirectory = new File(directory, "subdirectory"); final File file = new File(subdirectory, "file"); final File anotherDirectory = new File(workingCopyDirectory, "anotherDirectory"); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSource(SvnTarget.fromURL(url)); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.run(); final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setSingleTarget(SvnTarget.fromFile(file)); setLock.run(); final SvnScheduleForRemoval scheduleForRemoval = svnOperationFactory.createScheduleForRemoval(); scheduleForRemoval.setSingleTarget(SvnTarget.fromFile(file)); scheduleForRemoval.run(); final SvnCopy copy = svnOperationFactory.createCopy(); copy.setFailWhenDstExists(false); copy.setMove(true); copy.addCopySource(SvnCopySource.create(SvnTarget.fromFile(subdirectory), SVNRevision.WORKING)); copy.setSingleTarget(SvnTarget.fromFile(anotherDirectory)); copy.run(); final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); final Map<File, SvnStatus> statuses = TestUtil.getStatuses(svnOperationFactory, workingCopyDirectory); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(subdirectory).getNodeStatus()); Assert.assertEquals(SVNStatusType.STATUS_DELETED, statuses.get(file).getNodeStatus()); Assert.assertNotNull(statuses.get(file).getLock()); final SVNWCContext context = new SVNWCContext(svnOperationFactory.getOptions(), svnOperationFactory.getEventHandler()); try { final SVNStatus oldDirectoryStatus = SvnCodec.status(context, statuses.get(subdirectory)); Assert.assertNull(oldDirectoryStatus.getTreeConflict()); final SVNStatus oldFileStatus = SvnCodec.status(context, statuses.get(file)); Assert.assertNull(oldFileStatus.getTreeConflict()); } finally { context.close(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testMergeFileAdditionAndDeletion() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testMergeFileAdditionAndDeletion", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.addDirectory("directory1/directory"); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.addDirectoryByCopying("directory2", "directory1"); commitBuilder2.commit(); final CommitBuilder commitBuilder3 = new CommitBuilder(url); commitBuilder3.addFile("directory2/directory/file", "contents".getBytes()); commitBuilder3.commit(); final CommitBuilder commitBuilder4 = new CommitBuilder(url); commitBuilder4.delete("directory2/directory/file"); commitBuilder4.commit(); final SVNURL directory1Url = url.appendPath("directory1", false); final SVNURL directory2Url = url.appendPath("directory2", false); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(directory1Url); final File workingCopyDirectory = workingCopy.getWorkingCopyDirectory(); final SvnMerge merge = svnOperationFactory.createMerge(); merge.addRevisionRange(SvnRevisionRange.create(SVNRevision.create(2), SVNRevision.create(3))); merge.addRevisionRange(SvnRevisionRange.create(SVNRevision.create(3), SVNRevision.create(4))); merge.setSource(SvnTarget.fromURL(directory2Url), false); merge.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); merge.run(); Assert.assertFalse(workingCopy.getFile("directory/file").exists()); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testConflictOnFileExternalUpdate() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testConflictOnFileExternalUpdate", options); try { final SVNURL url = sandbox.createSvnRepository(); final SVNExternal external = new SVNExternal("file", url.appendPath("file", false).toString(), SVNRevision.HEAD, SVNRevision.HEAD, false, false, true); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.addDirectory("directory"); commitBuilder1.addFile("file"); commitBuilder1.setDirectoryProperty("directory", SVNProperty.EXTERNALS, SVNPropertyValue.create(external.toString())); commitBuilder1.commit(); final SVNURL directoryUrl = url.appendPath("directory", false); final File workingCopyDirectory = sandbox.createDirectory("wc"); final File file = new File(workingCopyDirectory, "file"); final SvnCheckout checkout = svnOperationFactory.createCheckout(); checkout.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); checkout.setSource(SvnTarget.fromURL(directoryUrl)); checkout.setIgnoreExternals(false); checkout.run(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.changeFile("file", "theirs".getBytes()); commitBuilder2.commit(); TestUtil.writeFileContentsString(file, "mine"); final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); final Set<String> expectedNames = new HashSet<String>(); expectedNames.add("file"); expectedNames.add("file.r1"); expectedNames.add("file.r2"); expectedNames.add("file.mine"); final Set<String> actualNames = new HashSet<String>(); final File[] files = SVNFileListUtil.listFiles(workingCopyDirectory); for (File child : files) { String name = SVNFileUtil.getFileName(child); if (SVNFileUtil.getAdminDirectoryName().equals(name)) { continue; } actualNames.add(name); } Assert.assertEquals(expectedNames, actualNames); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testMergeRecordsActualPropertiesForFileWithMergeInfo() throws Exception { final TestOptions options = TestOptions.getInstance(); Assume.assumeTrue(TestUtil.isNewWorkingCopyTest()); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testMergeRecordsActualPropertiesForFileWithMergeInfo", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.addFile("directory/file"); commitBuilder1.setFileProperty("directory/file", SVNProperty.MERGE_INFO, SVNPropertyValue.create("/somefile:1")); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.addFileByCopying("directory/copiedFile", "directory/file"); commitBuilder2.delete("directory/file"); commitBuilder2.commit(); final CommitBuilder commitBuilder3 = new CommitBuilder(url); commitBuilder3.addDirectoryByCopying("copiedDirectory", "directory", 1); commitBuilder3.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url.appendPath("copiedDirectory", false)); final File workingCopyDirectory = workingCopy.getWorkingCopyDirectory(); final SvnMerge merge = svnOperationFactory.createMerge(); merge.addRevisionRange(SvnRevisionRange.create(SVNRevision.create(1), SVNRevision.create(2))); merge.setSource(SvnTarget.fromURL(url.appendPath("directory", false)), false); merge.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); merge.run(); Assert.assertEquals(2, TestUtil.getTableSize(workingCopy, SVNWCDbSchema.ACTUAL_NODE.name())); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testImplicitGapIsExcludedFromMerging() throws Exception { //SVNKIT-305 final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testImplicitGapIsExcludedFromMerging", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.addFile("trunk/file"); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.delete("trunk/file"); commitBuilder2.commit(); final CommitBuilder commitBuilder3 = new CommitBuilder(url); commitBuilder3.addDirectoryByCopying("branches/branch", "trunk", 1); commitBuilder3.commit(); final CommitBuilder commitBuilder4 = new CommitBuilder(url); //implicit src gap commitBuilder4.commit(); final CommitBuilder commitBuilder5 = new CommitBuilder(url); commitBuilder5.delete("branches/branch"); commitBuilder5.commit(); final CommitBuilder commitBuilder6 = new CommitBuilder(url); commitBuilder6.addDirectoryByCopying("branches/branch", "trunk", 3); commitBuilder6.commit(); final CommitBuilder commitBuilder7 = new CommitBuilder(url); commitBuilder7.addFileByCopying("trunk/file", "trunk/file", 1); commitBuilder7.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url.appendPath("trunk", false)); final SVNClientManager clientManager = SVNClientManager.newInstance(); try { final SVNDiffClient diffClient = clientManager.getDiffClient(); workingCopy.setProperty(workingCopy.getFile("file"), SVNProperty.MERGE_INFO, SVNPropertyValue.create("/branches/branch/file:3")); //the value doesn't matter workingCopy.setProperty(workingCopy.getWorkingCopyDirectory(), SVNProperty.MERGE_INFO, SVNPropertyValue.create("/branches/branch:6-7")); Assert.assertEquals(8, workingCopy.commit("")); workingCopy.updateToRevision(-1); diffClient.doMerge(url.appendPath("branches/branch", false), SVNRevision.HEAD, Arrays.asList( new SVNRevisionRange(SVNRevision.create(1), SVNRevision.HEAD) ), workingCopy.getWorkingCopyDirectory(), SVNDepth.INFINITY, true, false, false, false); Assert.assertEquals(9, workingCopy.commit("")); } finally { clientManager.dispose(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testMergeAfterShallowMergeProducesCorrectMergeinfo() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testMergeAfterShallowMergeProducesCorrectMergeinfo", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.addFile("directory/subdirectory/file"); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.addDirectoryByCopying("copiedDirectory", "directory"); commitBuilder2.commit(); final CommitBuilder commitBuilder3 = new CommitBuilder(url); commitBuilder3.changeFile("directory/subdirectory/file", "contents".getBytes()); commitBuilder3.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url); final SvnMerge shallowMerge = svnOperationFactory.createMerge(); shallowMerge.addRevisionRange(SvnRevisionRange.create(SVNRevision.create(1), SVNRevision.HEAD)); shallowMerge.setSource(SvnTarget.fromURL(url.appendPath("directory", false)), false); shallowMerge.setSingleTarget(SvnTarget.fromFile(workingCopy.getFile("copiedDirectory"))); shallowMerge.setDepth(SVNDepth.FILES); shallowMerge.run(); final SvnMerge merge = svnOperationFactory.createMerge(); merge.addRevisionRange(SvnRevisionRange.create(SVNRevision.create(1), SVNRevision.HEAD)); merge.setSource(SvnTarget.fromURL(url.appendPath("directory", false)), false); merge.setSingleTarget(SvnTarget.fromFile(workingCopy.getFile("copiedDirectory"))); merge.setDepth(SVNDepth.INFINITY); merge.run(); final SvnGetProperties getProperties = svnOperationFactory.createGetProperties(); getProperties.setSingleTarget(SvnTarget.fromFile(workingCopy.getFile("copiedDirectory"))); final SVNProperties properties = getProperties.run(); Assert.assertEquals("/directory:2-3", SVNPropertyValue.getPropertyAsString(properties.getSVNPropertyValue(SVNProperty.MERGE_INFO))); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testPostponingConflictDoesntCreateEditedFile() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testPostponingConflictDoesntCreateEditedFile", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.addFile("file", "base".getBytes()); SVNCommitInfo commitInfo1 = commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.changeFile("file", "theirs".getBytes()); commitBuilder2.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url, commitInfo1.getNewRevision()); final File workingCopyDirectory = workingCopy.getWorkingCopyDirectory(); final File file = workingCopy.getFile("file"); TestUtil.writeFileContentsString(file, "mine"); final File anyFile = workingCopy.getFile("anyFile"); TestUtil.writeFileContentsString(anyFile, "anyFile"); final DefaultSVNOptions svnOptions = new DefaultSVNOptions(); svnOptions.setConflictHandler(new ISVNConflictHandler() { public SVNConflictResult handleConflict(SVNConflictDescription conflictDescription) throws SVNException { return new SVNConflictResult(SVNConflictChoice.POSTPONE, anyFile); } }); svnOperationFactory.setOptions(svnOptions); final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); update.run(); final File editedFile = workingCopy.getFile("file.edited"); Assert.assertFalse(editedFile.exists()); final SvnGetInfo getInfo = svnOperationFactory.createGetInfo(); getInfo.setSingleTarget(SvnTarget.fromFile(file)); final SvnInfo svnInfo = getInfo.run(); final Collection<SVNConflictDescription> conflicts = svnInfo.getWcInfo().getConflicts(); Assert.assertEquals(1, conflicts.size()); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } private void update(SvnOperationFactory svnOperationFactory, WorkingCopy workingCopy) throws SVNException { final SvnUpdate update = svnOperationFactory.createUpdate(); update.setSingleTarget(SvnTarget.fromFile(workingCopy.getWorkingCopyDirectory())); update.run(); } private void runResolve(SvnOperationFactory svnOperationFactory, File file, SVNConflictChoice resolution) throws SVNException { final SVNClientManager clientManager = SVNClientManager.newInstance(svnOperationFactory.getOptions(), svnOperationFactory.getRepositoryPool()); try { final SVNWCClient wcClient = clientManager.getWCClient(); wcClient.doResolve(file, SVNDepth.INFINITY, resolution); } finally { clientManager.dispose(); } } private String getTestName() { return "MergeTest"; } }