Return custom comparison service for checksum. Default to upload local version on checksum mismatch.

This commit is contained in:
David Kocher
2025-09-30 21:03:11 +02:00
parent 2bf2010a98
commit 0e2f30c5ee
10 changed files with 60 additions and 35 deletions
@@ -23,6 +23,11 @@ import ch.cyberduck.core.LoginOptions;
import ch.cyberduck.core.PathContainerService;
import ch.cyberduck.core.Protocol;
import ch.cyberduck.core.Scheme;
import ch.cyberduck.core.synchronization.ChainedComparisonService;
import ch.cyberduck.core.synchronization.ChecksumComparisonService;
import ch.cyberduck.core.synchronization.ComparisonService;
import ch.cyberduck.core.synchronization.DefaultComparisonService;
import ch.cyberduck.core.synchronization.ETagComparisonService;
import ch.cyberduck.core.text.DefaultLexicographicOrderComparator;
import org.apache.commons.codec.binary.Base64;
@@ -109,6 +114,9 @@ public class AzureProtocol extends AbstractProtocol {
if(type == PathContainerService.class) {
return (T) new DirectoryDelimiterPathContainerService();
}
if(type == ComparisonService.class) {
return (T) new DefaultComparisonService(new ChainedComparisonService(new ChecksumComparisonService(), new ETagComparisonService()), ComparisonService.disabled);
}
return super.getFeature(type);
}
}
@@ -19,6 +19,9 @@ import ch.cyberduck.core.AbstractProtocol;
import ch.cyberduck.core.LocaleFactory;
import ch.cyberduck.core.Protocol;
import ch.cyberduck.core.Scheme;
import ch.cyberduck.core.synchronization.ChecksumComparisonService;
import ch.cyberduck.core.synchronization.ComparisonService;
import ch.cyberduck.core.synchronization.DefaultComparisonService;
import com.google.auto.service.AutoService;
@@ -90,4 +93,13 @@ public class DropboxProtocol extends AbstractProtocol {
public Case getCaseSensitivity() {
return Case.insensitive;
}
@Override
@SuppressWarnings("unchecked")
public <T> T getFeature(final Class<T> type) {
if(type == ComparisonService.class) {
return (T) new DefaultComparisonService(new ChecksumComparisonService(), ComparisonService.disabled);
}
return super.getFeature(type);
}
}
@@ -63,6 +63,8 @@ public class DropboxMoveFeatureTest extends AbstractDropboxTest {
assertNotEquals(target.attributes().getVersionId(), file.attributes().getVersionId());
assertEquals(target.attributes().getModificationDate(), file.attributes().getModificationDate());
final PathAttributes targetAttributes = new DropboxAttributesFinderFeature(session).find(target);
assertEquals(file.attributes().getChecksum(), target.attributes().getChecksum());
assertEquals(target.attributes(), new DropboxAttributesFinderFeature(session).find(target));
assertEquals(Comparison.equal, session.getHost().getProtocol().getFeature(ComparisonService.class).compare(Path.Type.file, file.attributes(), targetAttributes));
assertEquals(target.attributes(), targetAttributes);
new DropboxDeleteFeature(session).delete(Collections.singletonList(target), new DisabledLoginCallback(), new Delete.DisabledCallback());
@@ -19,6 +19,9 @@ import ch.cyberduck.core.AbstractProtocol;
import ch.cyberduck.core.LocaleFactory;
import ch.cyberduck.core.Protocol;
import ch.cyberduck.core.Scheme;
import ch.cyberduck.core.synchronization.ChecksumComparisonService;
import ch.cyberduck.core.synchronization.ComparisonService;
import ch.cyberduck.core.synchronization.DefaultComparisonService;
import com.google.auto.service.AutoService;
@@ -85,4 +88,14 @@ public class DriveProtocol extends AbstractProtocol {
public VersioningMode getVersioningMode() {
return VersioningMode.storage;
}
@Override
@SuppressWarnings("unchecked")
public <T> T getFeature(final Class<T> type) {
if(type == ComparisonService.class) {
return (T) new DefaultComparisonService(new ChecksumComparisonService(), ComparisonService.disabled);
}
return super.getFeature(type);
}
}
@@ -58,14 +58,19 @@ public class DriveMoveFeatureTest extends AbstractDriveTest {
final DriveFileIdProvider fileid = new DriveFileIdProvider(session);
final Path test = new DriveTouchFeature(session, fileid).touch(new DriveWriteFeature(session, fileid), new Path(DriveHomeFinderService.MYDRIVE_FOLDER, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file)), new TransferStatus());
final String id = test.attributes().getFileId();
final Path folder = new Path(DriveHomeFinderService.MYDRIVE_FOLDER, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory));
new DriveDirectoryFeature(session, fileid).mkdir(new DriveWriteFeature(session, fileid), folder, new TransferStatus());
final Path folder = new DriveDirectoryFeature(session, fileid).mkdir(new DriveWriteFeature(session, fileid),
new Path(DriveHomeFinderService.MYDRIVE_FOLDER, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.directory)), new TransferStatus());
assertEquals(folder.attributes(), new DriveAttributesFinderFeature(session, fileid).find(folder));
final Path target = new DriveMoveFeature(session, fileid).move(test, new Path(folder, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file)), new TransferStatus(), new Delete.DisabledCallback(), new DisabledConnectionCallback());
assertEquals(id, target.attributes().getFileId());
assertEquals(test.attributes().getChecksum(), target.attributes().getChecksum());
assertNotEquals(test.attributes().getModificationDate(), target.attributes().getModificationDate());
final Find find = new DefaultFindFeature(session);
assertFalse(find.find(test));
assertTrue(find.find(target));
assertEquals(folder.attributes(), new DriveAttributesFinderFeature(session, fileid).find(folder));
final PathAttributes targetAttr = new DriveAttributesFinderFeature(session, fileid).find(target);
assertEquals(target.attributes(), targetAttr);
assertEquals(Comparison.equal, session.getHost().getProtocol().getFeature(ComparisonService.class).compare(Path.Type.file, test.attributes(), targetAttr));
new DriveDeleteFeature(session, fileid).delete(Arrays.asList(target, folder), new DisabledLoginCallback(), new Delete.DisabledCallback());
}
@@ -55,6 +55,8 @@ public class DriveWriteFeatureTest extends AbstractDriveTest {
final DriveFileIdProvider idProvider = new DriveFileIdProvider(session);
final Path folder = new DriveDirectoryFeature(session, idProvider).mkdir(
new DriveWriteFeature(session, idProvider), new Path(DriveHomeFinderService.MYDRIVE_FOLDER, UUID.randomUUID().toString(), EnumSet.of(Path.Type.directory)), new TransferStatus());
final PathAttributes folderAttributes = new DriveAttributesFinderFeature(session, idProvider).find(folder);
assertEquals(folderAttributes, folder.attributes());
final Path test = new Path(folder, new AlphanumericRandomStringService().random(), EnumSet.of(Path.Type.file));
String fileid;
{
@@ -83,6 +85,7 @@ public class DriveWriteFeatureTest extends AbstractDriveTest {
assertArrayEquals(content, buffer);
assertEquals("x-application/cyberduck", session.getClient().files().get(test.attributes().getFileId()).execute().getMimeType());
}
assertEquals(folderAttributes, new DriveAttributesFinderFeature(session, idProvider).find(folder));
{
// overwrite
final TransferStatus status = new TransferStatus();
@@ -24,17 +24,12 @@ import ch.cyberduck.core.PathContainerService;
import ch.cyberduck.core.Protocol;
import ch.cyberduck.core.Scheme;
import ch.cyberduck.core.features.Location;
import ch.cyberduck.core.synchronization.ChainedComparisonService;
import ch.cyberduck.core.synchronization.Comparison;
import ch.cyberduck.core.synchronization.ComparisonService;
import ch.cyberduck.core.synchronization.DefaultComparisonService;
import ch.cyberduck.core.synchronization.ETagComparisonService;
import ch.cyberduck.core.synchronization.SizeComparisonService;
import ch.cyberduck.core.synchronization.TimestampComparisonService;
import ch.cyberduck.core.text.DefaultLexicographicOrderComparator;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -138,10 +133,7 @@ public final class GoogleStorageProtocol extends AbstractProtocol {
return (T) new DirectoryDelimiterPathContainerService();
}
if(type == ComparisonService.class) {
return (T) new DefaultComparisonService(new ChainedComparisonService(EnumSet.of(Comparison.unknown, Comparison.notequal),
new ETagComparisonService(),
new ChainedComparisonService(
EnumSet.of(Comparison.unknown, Comparison.equal), new TimestampComparisonService(), new SizeComparisonService())), ComparisonService.disabled);
return (T) new DefaultComparisonService(new ETagComparisonService(), ComparisonService.disabled);
}
return super.getFeature(type);
}
@@ -15,16 +15,14 @@ package ch.cyberduck.core.hubic;
* GNU General Public License for more details.
*/
import ch.cyberduck.core.AbstractProtocol;
import ch.cyberduck.core.LocaleFactory;
import ch.cyberduck.core.Protocol;
import ch.cyberduck.core.Scheme;
import ch.cyberduck.core.openstack.SwiftProtocol;
import com.google.auto.service.AutoService;
@AutoService(Protocol.class)
public class HubicProtocol extends AbstractProtocol {
public class HubicProtocol extends SwiftProtocol {
@Override
public String getIdentifier() {
@@ -36,11 +34,6 @@ public class HubicProtocol extends AbstractProtocol {
return "hubiC";
}
@Override
public Scheme getScheme() {
return Scheme.https;
}
@Override
public Type getType() {
return Type.swift;
@@ -76,11 +69,6 @@ public class HubicProtocol extends AbstractProtocol {
return LocaleFactory.localizedString("Authorization code", "Credentials");
}
@Override
public DirectoryTimestamp getDirectoryTimestamp() {
return DirectoryTimestamp.explicit;
}
@Override
public boolean isUsernameConfigurable() {
return false;
@@ -18,6 +18,9 @@ package ch.cyberduck.core.manta;
import ch.cyberduck.core.AbstractProtocol;
import ch.cyberduck.core.Protocol;
import ch.cyberduck.core.Scheme;
import ch.cyberduck.core.synchronization.ComparisonService;
import ch.cyberduck.core.synchronization.DefaultComparisonService;
import ch.cyberduck.core.synchronization.ETagComparisonService;
import com.google.auto.service.AutoService;
@@ -88,4 +91,13 @@ public class MantaProtocol extends AbstractProtocol {
public VersioningMode getVersioningMode() {
return VersioningMode.custom;
}
@Override
@SuppressWarnings("unchecked")
public <T> T getFeature(final Class<T> type) {
if(type == ComparisonService.class) {
return (T) new DefaultComparisonService(new ETagComparisonService(), ComparisonService.disabled);
}
return super.getFeature(type);
}
}
@@ -18,16 +18,10 @@ package ch.cyberduck.core.onedrive;
import ch.cyberduck.core.AbstractProtocol;
import ch.cyberduck.core.LocaleFactory;
import ch.cyberduck.core.Scheme;
import ch.cyberduck.core.synchronization.ChainedComparisonService;
import ch.cyberduck.core.synchronization.Comparison;
import ch.cyberduck.core.synchronization.ComparisonService;
import ch.cyberduck.core.synchronization.DefaultComparisonService;
import ch.cyberduck.core.synchronization.SizeComparisonService;
import ch.cyberduck.core.synchronization.TimestampComparisonService;
import ch.cyberduck.core.synchronization.VersionIdComparisonService;
import java.util.EnumSet;
public abstract class GraphProtocol extends AbstractProtocol {
@Override
public Scheme getScheme() {
@@ -79,11 +73,7 @@ public abstract class GraphProtocol extends AbstractProtocol {
@SuppressWarnings("unchecked")
public <T> T getFeature(final Class<T> type) {
if(type == ComparisonService.class) {
return (T) new DefaultComparisonService(new ChainedComparisonService(EnumSet.of(Comparison.unknown, Comparison.notequal),
new VersionIdComparisonService(),
new ChainedComparisonService(
EnumSet.of(Comparison.unknown, Comparison.equal), new TimestampComparisonService(), new SizeComparisonService())
), ComparisonService.disabled);
return (T) new DefaultComparisonService(new VersionIdComparisonService(), ComparisonService.disabled);
}
return super.getFeature(type);
}