diff --git a/dracoon/src/main/java/ch/cyberduck/core/sds/SDSMoveFeature.java b/dracoon/src/main/java/ch/cyberduck/core/sds/SDSMoveFeature.java index 6c774f2f17..3efc68044b 100644 --- a/dracoon/src/main/java/ch/cyberduck/core/sds/SDSMoveFeature.java +++ b/dracoon/src/main/java/ch/cyberduck/core/sds/SDSMoveFeature.java @@ -15,6 +15,7 @@ package ch.cyberduck.core.sds; * GNU General Public License for more details. */ +import ch.cyberduck.core.CaseInsensitivePathPredicate; import ch.cyberduck.core.ConnectionCallback; import ch.cyberduck.core.DisabledListProgressListener; import ch.cyberduck.core.Path; @@ -54,9 +55,12 @@ public class SDSMoveFeature implements Move { @Override public Path move(final Path file, final Path renamed, final TransferStatus status, final Delete.Callback callback, final ConnectionCallback connectionCallback) throws BackgroundException { try { + // Handle case insensitive. Find feature will have reported target to exist if same name with different case if(status.isExists()) { - log.warn(String.format("Delete existing file %s", renamed)); - new SDSDeleteFeature(session, nodeid).delete(Collections.singletonMap(renamed, status), connectionCallback, callback); + if(!new CaseInsensitivePathPredicate(file).test(renamed)) { + log.warn(String.format("Delete existing file %s", renamed)); + new SDSDeleteFeature(session, nodeid).delete(Collections.singletonMap(renamed, status), connectionCallback, callback); + } } final long nodeId = Long.parseLong(nodeid.getFileid(file, new DisabledListProgressListener())); if(!new SimplePathPredicate(file.getParent()).test(renamed.getParent())) { diff --git a/dracoon/src/test/java/ch/cyberduck/core/sds/SDSDelegatingCopyFeatureTest.java b/dracoon/src/test/java/ch/cyberduck/core/sds/SDSDelegatingCopyFeatureTest.java index 4b5a04c524..643438e889 100644 --- a/dracoon/src/test/java/ch/cyberduck/core/sds/SDSDelegatingCopyFeatureTest.java +++ b/dracoon/src/test/java/ch/cyberduck/core/sds/SDSDelegatingCopyFeatureTest.java @@ -226,11 +226,11 @@ public class SDSDelegatingCopyFeatureTest extends AbstractSDSTest { room1.attributes().getAcl().addAll(new Acl.EmailUser(System.getProperties().getProperty("sds.user")), SDSPermissionsFeature.DELETE_ROLE); final SDSNodeIdProvider nodeid = new SDSNodeIdProvider(session).withCache(cache); final Path room2 = new SDSDirectoryFeature(session, nodeid).mkdir(new Path( - new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory, Path.Type.volume, Path.Type.triplecrypt)), null, new TransferStatus()); + new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory, Path.Type.volume)), null, new TransferStatus()); final byte[] content = RandomUtils.nextBytes(32769); final TransferStatus status = new TransferStatus(); status.setLength(content.length); - final Path test = new Path(room2, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file, Path.Type.triplecrypt)); + final Path test = new Path(room2, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file)); final SDSWriteFeature writer = new SDSWriteFeature(session, nodeid); final StatusOutputStream out = writer.write(test, status, new DisabledConnectionCallback()); assertNotNull(out); diff --git a/dracoon/src/test/java/ch/cyberduck/core/sds/SDSDelegatingMoveFeatureTest.java b/dracoon/src/test/java/ch/cyberduck/core/sds/SDSDelegatingMoveFeatureTest.java index 35b36f80af..4c1ce8bce2 100644 --- a/dracoon/src/test/java/ch/cyberduck/core/sds/SDSDelegatingMoveFeatureTest.java +++ b/dracoon/src/test/java/ch/cyberduck/core/sds/SDSDelegatingMoveFeatureTest.java @@ -78,6 +78,19 @@ public class SDSDelegatingMoveFeatureTest extends AbstractSDSTest { new SDSDeleteFeature(session, nodeid).delete(Collections.singletonList(room), new DisabledLoginCallback(), new Delete.DisabledCallback()); } + @Test + public void testRenameCaseChangeOnly() throws Exception { + final SDSNodeIdProvider nodeid = new SDSNodeIdProvider(session).withCache(cache); + final Path room = new SDSDirectoryFeature(session, nodeid).mkdir(new Path( + new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory, Path.Type.volume, Path.Type.triplecrypt)), null, new TransferStatus()); + final Path test = new SDSTouchFeature(session, nodeid).touch(new Path(room, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file)), new TransferStatus()); + final Path target = new Path(room, test.getName().toUpperCase(), EnumSet.of(Path.Type.file)); + final Path result = new SDSDelegatingMoveFeature(session, nodeid, new SDSMoveFeature(session, nodeid)).move(test, target, new TransferStatus().exists(true), new Delete.DisabledCallback(), new DisabledConnectionCallback()); + assertEquals(test.attributes().getVersionId(), result.attributes().getVersionId()); + assertEquals(0, session.getMetrics().get(Copy.class)); + new SDSDeleteFeature(session, nodeid).delete(Collections.singletonList(room), new DisabledLoginCallback(), new Delete.DisabledCallback()); + } + @Test public void testMoveDifferentDataRoom() throws Exception { final SDSNodeIdProvider nodeid = new SDSNodeIdProvider(session).withCache(cache); @@ -180,7 +193,7 @@ public class SDSDelegatingMoveFeatureTest extends AbstractSDSTest { final byte[] content = RandomUtils.nextBytes(32769); final TransferStatus status = new TransferStatus(); status.setLength(content.length); - final Path test = new Path(room2, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file, Path.Type.triplecrypt)); + final Path test = new Path(room2, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file)); final SDSWriteFeature writer = new SDSWriteFeature(session, nodeid); final StatusOutputStream out = writer.write(test, status, new DisabledConnectionCallback()); assertNotNull(out); @@ -375,8 +388,7 @@ public class SDSDelegatingMoveFeatureTest extends AbstractSDSTest { new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory, Path.Type.volume, Path.Type.triplecrypt)), null, new TransferStatus()); final String filename = new AlphanumericRandomStringService().random(); final Path test = new SDSTouchFeature(session, nodeid).touch(new Path(room, filename, EnumSet.of(Path.Type.file)), new TransferStatus()); - final Path target = new Path(room, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file)); - new SDSTouchFeature(session, nodeid).touch(target, new TransferStatus()); + final Path target = new SDSTouchFeature(session, nodeid).touch(new Path(room, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file)), new TransferStatus()); new SDSMoveFeature(session, nodeid).move(test, target, new TransferStatus().exists(true), new Delete.DisabledCallback(), new DisabledConnectionCallback()); assertFalse(new SDSFindFeature(nodeid).find(new Path(room, filename, EnumSet.of(Path.Type.file)))); assertTrue(new SDSFindFeature(nodeid).find(target)); @@ -390,8 +402,7 @@ public class SDSDelegatingMoveFeatureTest extends AbstractSDSTest { new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory, Path.Type.volume, Path.Type.triplecrypt)), null, new TransferStatus()); final String filename = new AlphanumericRandomStringService().random(); final Path test = new SDSTouchFeature(session, nodeid).touch(new Path(room, filename, EnumSet.of(Path.Type.file)), new TransferStatus()); - final Path target = new Path(room, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file)); - new SDSTouchFeature(session, nodeid).touch(target, new TransferStatus()); + final Path target = new SDSTouchFeature(session, nodeid).touch(new Path(room, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file)), new TransferStatus()); new SDSMoveFeature(session, nodeid).move(test, target, new TransferStatus().exists(true), new Delete.DisabledCallback(), new DisabledConnectionCallback()); assertFalse(new SDSFindFeature(nodeid).find(new Path(room, filename, EnumSet.of(Path.Type.file)))); assertTrue(new SDSFindFeature(nodeid).find(target));