package org.tmatesoft.svn.test; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; import org.junit.Test; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; import org.tmatesoft.svn.core.internal.wc17.SVNWCContext; import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration; 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 SvnRemoteStatusTest { @Before public void setup() { Assume.assumeTrue(!TestUtil.isNewWorkingCopyOnly()); } @Test public void testRemoteUrlIsNotNull() throws SVNException { testRemoteUrlPresence(SvnWcGeneration.V16); testRemoteUrlPresence(SvnWcGeneration.V17); } @Test public void testOldAndNewStatusValues() throws SVNException { Map<String, SVNStatus> newStatuses = collectStatuses(SvnWcGeneration.V17); Map<String, SVNStatus> oldStatuses = collectStatuses(SvnWcGeneration.V16); Assert.assertEquals(newStatuses.size(), oldStatuses.size()); for (Iterator<String> sts = newStatuses.keySet().iterator(); sts.hasNext();) { String path = sts.next(); SVNStatus newStatus = newStatuses.get(path); SVNStatus oldStatus = oldStatuses.get(path); Assert.assertNotNull(oldStatus); compare(newStatus, oldStatus); } } @Test public void testRemoteStatusDeletedFile() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testRemoteStatusDeletedFile", 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 workingCopyDirectory = workingCopy.getWorkingCopyDirectory(); final File file = new File(workingCopyDirectory, "file"); final SvnGetStatus getStatus = svnOperationFactory.createGetStatus(); getStatus.setSingleTarget(SvnTarget.fromFile(file)); getStatus.setRemote(true); final SvnStatus status = getStatus.run(); Assert.assertEquals(2, status.getRepositoryChangedRevision()); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testRemoteRevisionIsReported() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testRemoteRevisionIsReported", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.addFile("file"); commitBuilder.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url, 1); final File workingCopyDirectory = workingCopy.getWorkingCopyDirectory(); final File file = new File(workingCopyDirectory, "file"); //STATUS_COMPLETED should be called with a correct revision svnOperationFactory.setEventHandler(new ISVNEventHandler() { public void handleEvent(SVNEvent event, double progress) throws SVNException { if (event.getAction() == SVNEventAction.STATUS_COMPLETED) { Assert.assertEquals(1, event.getRevision()); } } public void checkCancelled() throws SVNCancelException { } }); final SvnGetStatus getStatus = svnOperationFactory.createGetStatus(); getStatus.setSingleTarget(SvnTarget.fromFile(file)); getStatus.setRemote(true); getStatus.setReportAll(false); getStatus.run(); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testSubdirectoryOfLocallyDeletedDirectory() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testSubdirectoryOfLocallyDeletedDirectory", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.addFile("directory/subdirectory/file"); commitBuilder.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url); final File workingCopyDirectory = workingCopy.getWorkingCopyDirectory(); final File directory = new File(workingCopyDirectory, "directory"); final File subdirectory = new File(directory, "subdirectory"); final SvnScheduleForRemoval scheduleForRemoval = svnOperationFactory.createScheduleForRemoval(); scheduleForRemoval.setSingleTarget(SvnTarget.fromFile(directory)); scheduleForRemoval.run(); SVNFileUtil.ensureDirectoryExists(directory); final int[] statusTargetsCount = {0}; final SvnGetStatus getStatus = svnOperationFactory.createGetStatus(); getStatus.setRemote(true); getStatus.setReportAll(false); getStatus.setSingleTarget(SvnTarget.fromFile(subdirectory)); getStatus.setReceiver(new ISvnObjectReceiver<SvnStatus>() { public void receive(SvnTarget target, SvnStatus status) throws SVNException { statusTargetsCount[0]++; Assert.assertEquals(SVNStatusType.STATUS_NONE, status.getRepositoryNodeStatus()); } }); getStatus.run(); Assert.assertEquals(2, statusTargetsCount[0]); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testRemoteLockIsReported() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testRemoteLockIsReported", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.addFile("file"); commitBuilder.commit(); //lock a file remotely final SVNURL fileUrl = url.appendPath("file", false); final String lockMessage = "lock message"; final SvnSetLock setLock = svnOperationFactory.createSetLock(); setLock.setLockMessage(lockMessage); setLock.setSingleTarget(SvnTarget.fromURL(fileUrl)); setLock.run(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url); final File workingCopyDirectory = workingCopy.getWorkingCopyDirectory(); final File file = new File(workingCopyDirectory, "file"); final SvnGetStatus getStatus = svnOperationFactory.createGetStatus(); getStatus.setRemote(true); getStatus.setSingleTarget(SvnTarget.fromFile(file)); final SvnStatus fileStatus = getStatus.run(); final SVNLock repositoryLock = fileStatus.getRepositoryLock(); Assert.assertNotNull(repositoryLock); Assert.assertEquals("/file", repositoryLock.getPath()); Assert.assertEquals(lockMessage, repositoryLock.getComment()); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testRemoteStatusRemotelyDeletedWorkingCopy() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testRemoteStatusRemotelyDeletedWorkingCopy", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.addFile("directory/file"); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.delete("directory"); commitBuilder2.commit(); final SVNURL subUrl = url.appendPath("directory", false); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(subUrl, 1); final File workingCopyDirectory = workingCopy.getWorkingCopyDirectory(); svnOperationFactory.setEventHandler(new ISVNEventHandler() { public void handleEvent(SVNEvent event, double progress) throws SVNException { if (event.getAction() == SVNEventAction.STATUS_COMPLETED) { Assert.assertEquals(-1, event.getRevision()); } } public void checkCancelled() throws SVNCancelException { } }); final SvnGetStatus getShortStatus = svnOperationFactory.createGetStatus(); getShortStatus.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); getShortStatus.setRemote(true); getShortStatus.setReportAll(false); getShortStatus.setReceiver(new ISvnObjectReceiver<SvnStatus>() { public void receive(SvnTarget target, SvnStatus status) throws SVNException { Assert.fail("No status should be reported for this working copy"); } }); getShortStatus.run(); final SvnGetStatus getFullStatus = svnOperationFactory.createGetStatus(); getFullStatus.setSingleTarget(SvnTarget.fromFile(workingCopyDirectory)); getFullStatus.setRemote(true); getFullStatus.setReportAll(true); getFullStatus.setReceiver(new ISvnObjectReceiver<SvnStatus>() { public void receive(SvnTarget target, SvnStatus status) throws SVNException { Assert.assertEquals(SVNStatusType.STATUS_DELETED, status.getRepositoryNodeStatus()); Assert.assertEquals(SVNStatusType.STATUS_NONE, status.getRepositoryPropertiesStatus()); Assert.assertEquals(SVNStatusType.STATUS_NONE, status.getRepositoryTextStatus()); } }); getFullStatus.run(); } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testRemoteStatusForLocallyAddedFile() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testRemoteStatusForLocallyAddedFile", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.addDirectory("directory"); commitBuilder.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url); final File file = workingCopy.getFile("directory/file"); SVNFileUtil.ensureDirectoryExists(file.getParentFile()); TestUtil.writeFileContentsString(file, "contents"); workingCopy.add(file); final SvnGetStatus getStatus = svnOperationFactory.createGetStatus(); getStatus.setSingleTarget(SvnTarget.fromFile(file)); getStatus.setRemote(true); final SvnStatus status = getStatus.run(); final SVNWCContext context = new SVNWCContext(svnOperationFactory.getOptions(), svnOperationFactory.getEventHandler()); try { final SVNStatus oldStatus = SvnCodec.status(context, status); Assert.assertEquals(url.appendPath("directory/file", false), oldStatus.getURL()); Assert.assertEquals(url, oldStatus.getRepositoryRootURL()); Assert.assertEquals("directory/file", oldStatus.getRepositoryRelativePath()); Assert.assertEquals(url, status.getRepositoryRootUrl()); Assert.assertEquals("directory/file", status.getRepositoryRelativePath()); } finally { context.close(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testRemoteStatusForRemotelyAddedFile() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testRemoteStatusForRemotelyAddedFile", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.addDirectory("directory"); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.addFile("directory/file"); commitBuilder2.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url, 1); final File file = workingCopy.getFile("directory/file"); final SvnGetStatus getStatus = svnOperationFactory.createGetStatus(); getStatus.setSingleTarget(SvnTarget.fromFile(file)); getStatus.setRemote(true); final SvnStatus status = getStatus.run(); final SVNWCContext context = new SVNWCContext(svnOperationFactory.getOptions(), svnOperationFactory.getEventHandler()); try { final SVNStatus oldStatus = SvnCodec.status(context, status); Assert.assertEquals(null, oldStatus.getURL()); Assert.assertEquals(url, oldStatus.getRepositoryRootURL()); Assert.assertEquals("directory/file", oldStatus.getRepositoryRelativePath()); Assert.assertEquals(url, status.getRepositoryRootUrl()); Assert.assertEquals("directory/file", status.getRepositoryRelativePath()); } finally { context.close(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } @Test public void testRemoteStatusForSwitchedFile() throws Exception { final TestOptions options = TestOptions.getInstance(); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); final Sandbox sandbox = Sandbox.createWithCleanup(getTestName() + ".testRemoteStatusForSwitchedFile", options); try { final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder1 = new CommitBuilder(url); commitBuilder1.addFile("directory1/file"); commitBuilder1.commit(); final CommitBuilder commitBuilder2 = new CommitBuilder(url); commitBuilder2.addFile("directory2/file"); commitBuilder2.commit(); final WorkingCopy workingCopy = sandbox.checkoutNewWorkingCopy(url, 1); final File directory1 = workingCopy.getFile("directory1"); final File file = workingCopy.getFile("directory1/file"); SvnSwitch svnSwitch = svnOperationFactory.createSwitch(); svnSwitch.setIgnoreAncestry(true); svnSwitch.setSingleTarget(SvnTarget.fromFile(directory1)); svnSwitch.setSwitchTarget(SvnTarget.fromURL(url.appendPath("directory2", false))); svnSwitch.run(); final SvnGetStatus getStatus = svnOperationFactory.createGetStatus(); getStatus.setSingleTarget(SvnTarget.fromFile(file)); getStatus.setRemote(true); final SvnStatus status = getStatus.run(); final SVNWCContext context = new SVNWCContext(svnOperationFactory.getOptions(), svnOperationFactory.getEventHandler()); try { final SVNStatus oldStatus = SvnCodec.status(context, status); Assert.assertEquals(url.appendPath("directory2/file", false), oldStatus.getURL()); Assert.assertEquals(url, oldStatus.getRepositoryRootURL()); Assert.assertEquals("directory2/file", oldStatus.getRepositoryRelativePath()); Assert.assertEquals(url, status.getRepositoryRootUrl()); Assert.assertEquals("directory2/file", status.getRepositoryRelativePath()); } finally { context.close(); } } finally { svnOperationFactory.dispose(); sandbox.dispose(); } } private void compare(SVNStatus newStatus, SVNStatus oldStatus) { Assert.assertEquals(oldStatus.getRemoteRevision(), newStatus.getRemoteRevision()); Assert.assertEquals(oldStatus.getRevision(), newStatus.getRevision()); Assert.assertEquals(oldStatus.getDepth(), newStatus.getDepth()); Assert.assertEquals(oldStatus.getCopyFromRevision(), newStatus.getCopyFromRevision()); Assert.assertEquals(oldStatus.getCopyFromURL(), newStatus.getCopyFromURL()); } private void testRemoteUrlPresence(SvnWcGeneration wcGeneration) throws SVNException { final TestOptions options = TestOptions.getInstance(); final Sandbox sandbox = Sandbox.createWithCleanup(getClass().getSimpleName() + "." + wcGeneration, options); final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.addDirectory("trunk"); commitBuilder.addFile("trunk/remotelyChanged.txt"); commitBuilder.addDirectory("trunk/remotelyChanged"); commitBuilder.addFile("trunk/remotelyDeleted.txt"); commitBuilder.addDirectory("trunk/remotelyDeleted"); commitBuilder.addFile("trunk/remotelyReplaced.txt"); commitBuilder.addDirectory("trunk/remotelyReplaced"); commitBuilder.commit(); // move WorkingCopy wc = sandbox.checkoutNewWorkingCopy(url, -1, true, wcGeneration); final SvnOperationFactory svnOperationFactory = wc.getOperationFactory(); // make changes final CommitBuilder remoteChange = new CommitBuilder(url); remoteChange.addFile("trunk/remotelyAdded.txt"); remoteChange.addDirectory("trunk/remotelyAdded"); remoteChange.delete("trunk/remotelyDeleted"); remoteChange.delete("trunk/remotelyDeleted.txt"); remoteChange.delete("trunk/remotelyReplaced"); remoteChange.delete("trunk/remotelyReplaced.txt"); remoteChange.addFile("trunk/remotelyReplaced.txt"); remoteChange.addDirectory("trunk/remotelyReplaced"); remoteChange.changeFile("trunk/remotelyChanged.txt", "change".getBytes()); remoteChange.commit(); SvnGetStatus st = svnOperationFactory.createGetStatus(); st.setSingleTarget(SvnTarget.fromFile(wc.getWorkingCopyDirectory())); st.setRemote(true); Collection<SvnStatus> statuses = new ArrayList<SvnStatus>(); st.run(statuses); for (SvnStatus status : statuses) { String remotePath = status.getRepositoryRelativePath(); SVNURL repositoryRoot = status.getRepositoryRootUrl(); Assert.assertNotNull(repositoryRoot); Assert.assertNotNull(remotePath); } } private Map<String, SVNStatus> collectStatuses(SvnWcGeneration wcGeneration) throws SVNException { final TestOptions options = TestOptions.getInstance(); final Sandbox sandbox = Sandbox.createWithCleanup(getClass().getSimpleName() + "." + wcGeneration, options); final SVNURL url = sandbox.createSvnRepository(); final CommitBuilder commitBuilder = new CommitBuilder(url); commitBuilder.addDirectory("trunk"); commitBuilder.addFile("trunk/remotelyChanged.txt"); commitBuilder.addDirectory("trunk/remotelyChanged"); commitBuilder.addFile("trunk/remotelyDeleted.txt"); commitBuilder.addDirectory("trunk/remotelyDeleted"); commitBuilder.addFile("trunk/remotelyReplaced.txt"); commitBuilder.addDirectory("trunk/remotelyReplaced"); commitBuilder.commit(); // move WorkingCopy wc = sandbox.checkoutNewWorkingCopy(url, -1, true, wcGeneration); // make changes final CommitBuilder remoteChange = new CommitBuilder(url); remoteChange.addFile("trunk/remotelyAdded.txt"); remoteChange.addDirectory("trunk/remotelyAdded"); remoteChange.delete("trunk/remotelyDeleted"); remoteChange.delete("trunk/remotelyDeleted.txt"); remoteChange.delete("trunk/remotelyReplaced"); remoteChange.delete("trunk/remotelyReplaced.txt"); remoteChange.addFile("trunk/remotelyReplaced.txt"); remoteChange.addDirectory("trunk/remotelyReplaced"); remoteChange.changeFile("trunk/remotelyChanged.txt", "change".getBytes()); remoteChange.commit(); final Map<String, SVNStatus> result = new HashMap<String, SVNStatus>(); SVNStatusClient stClient = SVNClientManager.newInstance().getStatusClient(); stClient.doStatus(wc.getWorkingCopyDirectory(), SVNRevision.WORKING, SVNDepth.INFINITY, true, true, true, false, new ISVNStatusHandler() { public void handleStatus(SVNStatus status) throws SVNException { result.put(status.getRepositoryRelativePath(), status); } }, null); return result; } private String getTestName() { return "SvnRemoteStatusTest"; } }