diff --git a/README.md b/README.md index 7b73f49..5d5af9d 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ partial, alternate, and planned behavior. | `-a, --archive` | Archive mode: enables `-c -m -M` (no `-s`) | | `-m` | Multithreading mode | | `-s` | Chunk serialization (batch all files per chunk) | +| `--secluded-args` | Accepted as an rsync compatibility option with no effect; `-s` remains chunk serialization. | | `-f, --sendfile` | Sendfile zero-copy. Incompatible with `-c` / `-s`. TCP only. | | `-M, --preserve` | Preserve supported file metadata (mode and mtime; ownership and atime are unsupported) | | `-n, --dry-run` | Scan and print what would be transferred | @@ -361,6 +362,11 @@ particular, FastSync currently uses `-p` for SSH port, `-s` for chunk serialization, and `-S` for sparse handling. These meanings must be reconciled before FastSync can claim full rsync CLI compatibility. +`--secluded-args` is accepted as a long-form compatibility no-op. It does not +change FastSync's transport or protocol behavior. The rsync short form `-s` is +intentionally not aliased because it remains FastSync's chunk-serialization +option. + ## Client Options ### Selection and transfer diff --git a/RSYNC_COMPAT.md b/RSYNC_COMPAT.md index 1370073..4b224a1 100644 --- a/RSYNC_COMPAT.md +++ b/RSYNC_COMPAT.md @@ -9,7 +9,8 @@ This document maps rsync's full feature set to FastSync's current implementation | ✅ Implemented | 35 | Feature works end-to-end | | 🔀 Alt Arg | 4 | Functionality exists but under different flag/semantics | | ⚠️ Partial | 5 | Flag parsed/stored but behavior incomplete | -| ❌ Not Implemented | 97 | Flag not recognized or no behavior | +| 🔄 Compatibility No-op | 1 | Flag is accepted for CLI compatibility but has no effect | +| ❌ Not Implemented | 96 | Flag not recognized or no behavior | | **Total** | **141** | | --- @@ -233,7 +234,7 @@ This document maps rsync's full feature set to FastSync's current implementation | `--protocol=NUM` | Force older protocol version | ❌ Not Implemented | | | `--iconv=CONVERT_SPEC` | Charset conversion | ❌ Not Implemented | | | `--checksum-seed=NUM` | Set checksum seed | ❌ Not Implemented | | -| `-s`, `--secluded-args` | Use protocol to send args | ❌ Not Implemented | | +| `--secluded-args` | Use protocol to send args | 🔄 Compatibility No-op | Accepted for CLI compatibility; it does not change FastSync transport or protocol behavior. `-s` remains chunk serialization. | | `--no-OPTION` | Turn off implied option | ❌ Not Implemented | | --- diff --git a/src/client/client_cli.c b/src/client/client_cli.c index 0df49a8..924b37b 100644 --- a/src/client/client_cli.c +++ b/src/client/client_cli.c @@ -186,6 +186,7 @@ static int config_add_pattern(char*** patterns, int* count, const char* value, typedef enum { OPT_FLAG, + OPT_NOOP, OPT_STRING, OPT_POS_INT, OPT_NONNEG_INT, @@ -196,10 +197,10 @@ typedef struct { const char* name; const char* alias; OptKind kind; - size_t offset; /* offsetof of the target field in Config */ + size_t offset; /* offsetof of the target field in Config, or 0 for OPT_NOOP */ } OptionEntry; -/* Options that map directly onto a Config field with no side effects. */ +/* Options parsed directly into Config, plus compatibility options with no effect. */ static const OptionEntry OPTION_TABLE[] = { {"--dry-run", "-n", OPT_FLAG, offsetof(Config, dry_run)}, {"--remove-source-files", NULL, OPT_FLAG, offsetof(Config, remove_source_files)}, @@ -213,6 +214,7 @@ static const OptionEntry OPTION_TABLE[] = { {"--stats", NULL, OPT_FLAG, offsetof(Config, stats)}, {"--human-readable", "-h", OPT_FLAG, offsetof(Config, human_readable)}, {"--partial", NULL, OPT_FLAG, offsetof(Config, partial)}, + {"--secluded-args", NULL, OPT_NOOP, 0}, {"--links", "-l", OPT_FLAG, offsetof(Config, follow_symlinks)}, {"--copy-links", NULL, OPT_FLAG, offsetof(Config, copy_links)}, {"--safe-links", NULL, OPT_FLAG, offsetof(Config, safe_links)}, @@ -254,11 +256,16 @@ static const OptionEntry* find_table_option(const char* arg) { } static int apply_table_option(Config* config, const OptionEntry* entry, const char* value) { + if (entry->kind == OPT_NOOP) + return 0; + void* field = (char*)config + entry->offset; switch (entry->kind) { case OPT_FLAG: *(bool*)field = true; return 0; + case OPT_NOOP: + return 0; case OPT_STRING: return set_string_option((char**)field, value, entry->name); case OPT_POS_INT: diff --git a/src/client/usage.c b/src/client/usage.c index 9201ef5..9025a82 100644 --- a/src/client/usage.c +++ b/src/client/usage.c @@ -37,6 +37,7 @@ void print_usage(void) { DELTA_MAX_FILE_SIZE); printf(" -m Enable multithreading\n"); printf(" -s Enable chunk serialization\n"); + printf(" --secluded-args Accept rsync compatibility option (no effect)\n"); printf(" -f Enable sendfile (TCP only, not with -c or -s)\n"); printf(" -v, --verbose Enable debug logging\n"); printf(" -q, --quiet Suppress non-error output\n"); diff --git a/tests/test_client_cli.c b/tests/test_client_cli.c index d490239..22e4fb3 100644 --- a/tests/test_client_cli.c +++ b/tests/test_client_cli.c @@ -434,6 +434,29 @@ static void test_parse_args_fsync() { config_delete(cfg); } +/* --secluded-args is accepted for compatibility but has no effect. */ +static void test_parse_args_secluded_args() { + Config* cfg = config_create(); + char* argv[] = {"fastsync", "--secluded-args", "/src", "/dst"}; + int positional_args[2]; + int positional_count = 0; + + EXPECT_EQ_INT(parse_args(cfg, 4, argv, positional_args, &positional_count), 0); + EXPECT_FALSE(cfg->use_chunk_serialization); + config_delete(cfg); +} + +static void test_parse_args_short_s_remains_chunk_serialization() { + Config* cfg = config_create(); + char* argv[] = {"fastsync", "-s", "/src", "/dst"}; + int positional_args[2]; + int positional_count = 0; + + EXPECT_EQ_INT(parse_args(cfg, 4, argv, positional_args, &positional_count), 0); + EXPECT_TRUE(cfg->use_chunk_serialization); + config_delete(cfg); +} + static void test_parse_args_8_bit_output() { Config* cfg = config_create(); char* long_argv[] = {"fastsync", "--8-bit-output", "/src", "/dst"}; @@ -484,7 +507,6 @@ static void test_parse_args_rejects_unsupported_stderr_modes() { } log_set_stderr_mode(LOG_STDERR_ERRORS); } - void test_client_cli() { test_validate_config_required_paths(); test_validate_config_incompatible_options(); @@ -517,4 +539,6 @@ void test_client_cli() { test_parse_args_8_bit_output(); test_parse_args_stderr_modes(); test_parse_args_rejects_unsupported_stderr_modes(); + test_parse_args_secluded_args(); + test_parse_args_short_s_remains_chunk_serialization(); }