diff --git a/src/client/client_cli.c b/src/client/client_cli.c index 5778f41..1760226 100644 --- a/src/client/client_cli.c +++ b/src/client/client_cli.c @@ -418,6 +418,7 @@ static const OptionEntry OPTION_TABLE[] = { {"--modify-window", "-@", OPT_NONNEG_INT, offsetof(Config, modify_window)}, {"--delta", NULL, OPT_FLAG, offsetof(Config, use_delta)}, {"--whole-file", "-W", OPT_FLAG, offsetof(Config, whole_file)}, + {"--fuzzy", "-y", OPT_FLAG, offsetof(Config, fuzzy)}, {"--save-to-disk", NULL, OPT_FLAG, offsetof(Config, save_to_disk)}, {"--progress", NULL, OPT_FLAG, offsetof(Config, show_progress)}, {"--tls", NULL, OPT_FLAG, offsetof(Config, use_tls)}, @@ -487,6 +488,7 @@ static const NegatableOption NEGATABLE_OPTIONS[] = { {"delete", NULL, offsetof(Config, use_delete)}, {"incremental", NULL, offsetof(Config, use_incremental)}, {"delta", NULL, offsetof(Config, use_delta)}, + {"fuzzy", NULL, offsetof(Config, fuzzy)}, {"save-to-disk", NULL, offsetof(Config, save_to_disk)}, {"progress", NULL, offsetof(Config, show_progress)}, {"tls", NULL, offsetof(Config, use_tls)}, @@ -608,6 +610,9 @@ static int apply_table_option(Config* config, const OptionEntry* entry, const ch int parse_args(Config* config, int argc, char* argv[], int* positional_args, int* positional_count) { bool verbose = false; + /* --no-delta seen on the command line: the user explicitly switched the + delta machinery off, so the --fuzzy implication must not override it. */ + bool no_delta = false; protocol_set_8_bit_output(config->eight_bit_output); /* Apply output controls before processing other options so their order is irrelevant. */ @@ -637,6 +642,8 @@ int parse_args(Config* config, int argc, char* argv[], int* positional_args, continue; } if (strncmp(argv[i], "--no-", strlen("--no-")) == 0) { + if (strcmp(argv[i], "--no-delta") == 0) + no_delta = true; if (apply_negation(config, argv[i]) != 0) return -1; continue; @@ -1068,6 +1075,19 @@ int parse_args(Config* config, int argc, char* argv[], int* positional_args, if (config_has_basis(config)) config->use_incremental = true; + /* -y/--fuzzy reuses an existing similar-named destination file as the delta + * basis, so it is meaningless without the receiver-driven delta path: + * imply --incremental, and --delta unless --whole-file (or an explicit + * --no-delta) switched the delta machinery off. FastSync has delta OFF by + * default (unlike rsync), so a bare --fuzzy must turn it on or it would be + * a silent no-op. --whole-file/--no-delta after --fuzzy therefore leave + * fuzzy inert, matching rsync where --fuzzy only affects delta transfers. */ + if (config->fuzzy) { + config->use_incremental = true; + if (!config->whole_file && !no_delta) + config->use_delta = true; + } + /* Incremental and delta transfers need metadata unless the user disabled it. */ if ((config->use_incremental || config->use_delta) && !config->use_metadata && !config->metadata_explicitly_disabled) { diff --git a/src/client/usage.c b/src/client/usage.c index 0cb0d76..268299b 100644 --- a/src/client/usage.c +++ b/src/client/usage.c @@ -81,6 +81,11 @@ void print_usage(void) { "used)\n"); printf(" --delta Delta transfer for changed files (requires --incremental)\n"); printf(" -W, --whole-file Transfer changed files without delta processing\n"); + printf(" -y, --fuzzy Use a similar-named file already in the destination\n"); + printf(" directory as the delta basis when the destination has no\n"); + printf(" usable file at the exact path (saves bandwidth; implies\n"); + printf(" --incremental and --delta; inert with --whole-file)\n"); + printf(" --no-fuzzy Disable --fuzzy\n"); printf(" --delta-block Delta block size in bytes (default: %d)\n", DELTA_BLOCK_SIZE_DEFAULT); printf(" --delta-max Max file size for delta transfer (default: %llu)\n",