diff --git a/README.md b/README.md index 1386d72..cabb909 100644 --- a/README.md +++ b/README.md @@ -66,8 +66,9 @@ replacement for every rsync feature or protocol mode. - Owner/group, ACL, xattr, hard-link, device, and special-file handling is incomplete or unavailable. - Sparse-file handling does not yet preserve all holes correctly. -- `--partial`, `--partial-dir`, `--append`, and `--append-verify` are not yet - full rsync-style resumable transfers. +- `--partial`, `--partial-dir`, `-P`, `--append`, and `--append-verify` are not + yet full rsync-style resumable transfers. Interrupted files are not retained + for resumption. - Several rsync short options currently have FastSync-specific meanings. Do not assume every short option is interchangeable yet. @@ -97,6 +98,7 @@ partial, alternate, and planned behavior. | `-v, --verbose` | Enable debug logging | | `-q, --quiet` | Suppress non-error output | | `--progress` | Show real-time transfer speed | +| `-P` | Enables partial-transfer mode and progress output (partial retention is incomplete) | | `--delete` | Delete files on receiver not present in source | | `--exclude ` | Exclude files matching glob pattern (repeatable) | | `--exclude-from ` | Read exclude patterns from a file (one per line) | diff --git a/RSYNC_COMPAT.md b/RSYNC_COMPAT.md index d71a103..6204d3f 100644 --- a/RSYNC_COMPAT.md +++ b/RSYNC_COMPAT.md @@ -40,7 +40,7 @@ This document maps rsync's full feature set to FastSync's current implementation | `-h`, `--human-readable` | Human-readable numbers | ✅ Implemented | Formats transfer byte sizes using binary units | | `-i`, `--itemize-changes` | Per-file change summary | ❌ Not Implemented | Removed because it had no effect | | `--progress` | Show progress | ✅ Implemented | Progress callback in sender | -| `-P` | Same as --partial --progress | ❌ Not Implemented | | +| `-P` | Same as --partial --progress | ⚠️ Partial | Parses and enables progress, but interrupted files are not retained for resumable transfers | | `--out-format=FORMAT` | Custom output format | ❌ Not Implemented | Removed because it had no effect | | `--log-file=FILE` | Log to file | ✅ Implemented | `log_file` config field | | `--log-file-format=FMT` | Log format | ❌ Not Implemented | | diff --git a/src/client/client_cli.c b/src/client/client_cli.c index 770e815..4a3ca80 100644 --- a/src/client/client_cli.c +++ b/src/client/client_cli.c @@ -541,6 +541,11 @@ int parse_args(Config* config, int argc, char* argv[], int* positional_args, } for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "-P") == 0) { + config->partial = true; + config->show_progress = true; + continue; + } if (strncmp(argv[i], "--no-", strlen("--no-")) == 0) { if (apply_negation(config, argv[i]) != 0) return -1; @@ -581,6 +586,7 @@ int parse_args(Config* config, int argc, char* argv[], int* positional_args, } continue; } + const OptionEntry* entry = find_table_option(argv[i]); const char* inline_value = NULL; if (!entry) diff --git a/src/client/usage.c b/src/client/usage.c index f754440..94c9d4e 100644 --- a/src/client/usage.c +++ b/src/client/usage.c @@ -21,6 +21,7 @@ void print_usage(void) { printf(" --remove-source-files Remove regular source files after successful transfer\n"); printf(" -p SSH port (default: 22)\n"); printf(" --progress Show transfer progress\n"); + printf(" -P Partial mode with progress (retention incomplete)\n"); printf(" -8, --8-bit-output Leave high-bit characters unescaped in output\n"); printf(" --delete Delete files on receiver not in source\n"); printf(" --ignore-existing Skip files that already exist on receiver\n"); diff --git a/tests/test_client_cli.c b/tests/test_client_cli.c index 8dda975..435ffcc 100644 --- a/tests/test_client_cli.c +++ b/tests/test_client_cli.c @@ -928,6 +928,22 @@ static void test_parse_args_compression_aliases() { config_delete(cfg); } +/* Test rsync-compatible -P parsing; resumable partial-file retention is not implied. */ +static void test_parse_args_partial_progress() { + Config* cfg = config_create(); + char* argv[] = {"fastsync", "-P", "/src", "/dst"}; + int positional_args[2]; + int positional_count = 0; + + int ret = parse_args(cfg, 4, argv, positional_args, &positional_count); + EXPECT_EQ_INT(ret, 0); + EXPECT_TRUE(cfg->partial); + EXPECT_TRUE(cfg->show_progress); + EXPECT_EQ_INT(positional_count, 2); + + config_delete(cfg); +} + static void test_parse_args_compression_equals_and_none() { Config* cfg = config_create(); char* argv[] = {"fastsync", "-z", "--zc=none", "--zl=7", "/src", "/dst"}; @@ -1043,7 +1059,7 @@ void test_client_cli() { test_parse_args_info_verbose_order(); test_parse_args_rejects_invalid_info_flag(); test_parse_args_archive(); - test_parse_args_negations(); +test_parse_args_negations(); test_parse_args_negation_order(); test_parse_args_no_preserve_blocks_implicit_metadata(); test_parse_args_rejects_unsafe_negation(); @@ -1063,4 +1079,5 @@ void test_client_cli() { test_parse_args_compression_alias_equals(); test_parse_args_rejects_invalid_compression_level_equals(); test_parse_args_rejects_invalid_compression_choice(); + test_parse_args_partial_progress(); }