Merge branch 'fix/parity-tests' into feat/parity-completion

This commit is contained in:
2026-09-17 01:38:19 +02:00
10 changed files with 485 additions and 92 deletions
+9 -1
View File
@@ -590,7 +590,15 @@ void change_emit_file_sent_bytes(const Config* config, const File* file,
event.bytes_sent = 0;
} else {
event.bytes_sent = bytes_sent;
event.bytes_read = bytes_read;
/* rsync's %c is the block-checksum bytes received for the file. Even a
* whole-file transfer (no basis; --append/--inplace included) receives
* rsync's 16-byte sum header, so rsync reports 16; a dry run transfers
* nothing and reports 0. FastSync's whole-file path has no sum header, so
* report rsync's value for parity. With delta enabled the real received
* bytes are kept, but FastSync's signature framing differs from rsync's so
* those stay numerically divergent. */
bool delta_active = config->use_delta && !config->whole_file;
event.bytes_read = (!config->dry_run && !delta_active) ? 16 : bytes_read;
}
char* name = NULL;
char* path = NULL;
+5 -3
View File
@@ -69,7 +69,8 @@ char* change_render_itemize_code(const Config* config, const ChangeEvent* event)
/* Expand an --out-format/--log-file-format template. Supported tokens:
* %i itemize code %n transfer-relative name (dir: trailing /)
* %f long display path %l file length in bytes
* %b wire bytes transferred %c wire bytes read back for the file
* %b wire bytes transferred %c block-checksum bytes received (rsync: 16
* for a whole-file transfer, 0 for a dry run)
* %C whole-file checksum hex (xxh128 by default; spaces for non-regular)
* %M mtime (YYYY/MM/DD-HH:MM:SS)
* %t current time %o operation ("send"/"del.")
@@ -91,8 +92,9 @@ char* change_render_list_line(const Config* config, const ChangeEvent* event);
void change_emit(const Config* config, const ChangeEvent* event);
/* Build and emit a CHANGE_SENT event for a file the client just sent. `bytes_sent`
* / `bytes_read` are the process-wide wire-byte deltas for this file (rsync's
* %b / %c); pass 0 when unknown. */
* is the process-wide wire-byte delta for this file (rsync's %b) and `bytes_read`
* the received bytes used for the delta handshake; pass 0 when unknown. For a
* whole-file transfer %c is pinned to rsync's 16-byte sum header regardless. */
void change_emit_file_sent_bytes(const Config* config, const File* file,
unsigned long long bytes_sent, unsigned long long bytes_read);
+34
View File
@@ -480,6 +480,36 @@ static bool split_flag_level(const char* token, char* name, size_t name_size, in
return true;
}
/* rsync --debug/--info categories that FastSync accepts for CLI parity but has
* no output wired to (yet). They must parse successfully so a valid rsync
* invocation is not rejected up front; only categories with a FastSync
* counterpart set a log flag. `pack`/`util` are FastSync-specific (packed
* metadata / general utility logging). `syms`, `hl`, and `owner` are aliases
* of rsync's `symsafe`, `hlink`, and `own`. */
static bool is_accepted_debug_category(const char* name) {
static const char* const categories[] = {
"acl", "backup", "bind", "chdir", "cmd", "connect", "del", "deltasum",
"dup", "exit", "filter", "flist", "fuzzy", "genr", "hash", "hl",
"hlink", "iconv", "nstr", "own", "owner", "recv", "send", "time",
};
for (size_t i = 0; i < sizeof(categories) / sizeof(categories[0]); i++) {
if (strcmp(name, categories[i]) == 0)
return true;
}
return false;
}
static bool is_accepted_info_category(const char* name) {
static const char* const categories[] = {
"backup", "del", "flist", "mount", "nonreg", "progress", "remove", "syms", "symsafe",
};
for (size_t i = 0; i < sizeof(categories) / sizeof(categories[0]); i++) {
if (strcmp(name, categories[i]) == 0)
return true;
}
return false;
}
static int parse_debug_flags(const char* value, Config* config) {
if (!value || value[0] == '\0' || value[0] == ',' || value[strlen(value) - 1] == ',' ||
strstr(value, ",,")) {
@@ -522,6 +552,8 @@ static int parse_debug_flags(const char* value, Config* config) {
flag = LOG_DEBUG_PACK;
} else if (strcmp(name, "util") == 0) {
flag = LOG_DEBUG_UTIL;
} else if (is_accepted_debug_category(name)) {
continue;
} else {
log_message(LOG_LEVEL_ERROR, "unsupported --debug flag: %s", token);
free(flags);
@@ -584,6 +616,8 @@ static int parse_info_flags(const char* value, Config* config) {
flag = LOG_INFO_SKIP;
else if (strcmp(name, "stats") == 0)
flag = LOG_INFO_STATS;
else if (is_accepted_info_category(name))
continue;
else {
log_message(LOG_LEVEL_ERROR, "unsupported --info flag: %s", token);
free(flags);
+9 -4
View File
@@ -341,15 +341,20 @@ void print_usage(void) {
}
void print_debug_usage(void) {
printf("Supported debug flags: IO,PROTO,PACK,UTIL,ALL,NONE\n");
printf("Emitting debug flags: IO,PROTO,PACK,UTIL,ALL,NONE\n");
printf("Also accepted for rsync CLI parity (silent): ACL,BACKUP,BIND,CHDIR,\n");
printf("CONNECT,CMD,DEL,DELTASUM,DUP,EXIT,FILTER,FLIST,FUZZY,GENR,HASH,HLINK,\n");
printf("ICONV,NSTR,OWN,RECV,SEND,TIME.\n");
printf("Flags may be comma-separated, for example: --debug=io,proto\n");
printf("An optional level suffix is accepted (e.g. --debug=io2); level 0\n");
printf("silences that item. Other rsync debug flags are unsupported and rejected.\n");
printf("silences that item. Unknown names are rejected.\n");
}
void print_info_usage(void) {
printf("Supported info flags: COPY,NAME,MISC,SKIP,STATS,ALL,NONE\n");
printf("Emitting info flags: COPY,NAME,MISC,SKIP,STATS,ALL,NONE\n");
printf("Also accepted for rsync CLI parity (silent): BACKUP,DEL,FLIST,MOUNT,\n");
printf("NONREG,PROGRESS,REMOVE,SYMSAFE.\n");
printf("Flags may be comma-separated, for example: --info=name,stats\n");
printf("An optional level suffix is accepted (e.g. --info=stats2); level 0\n");
printf("silences that item. Other rsync info flags are unsupported and rejected.\n");
printf("silences that item. Unknown names are rejected.\n");
}