Merge remote-tracking branch 'origin/feat/human-readable' into dev
# Conflicts: # RSYNC_COMPAT.md # src/client/client_send.c # tests/test_client_cli.c
This commit is contained in:
@@ -146,6 +146,7 @@ static const OptionEntry OPTION_TABLE[] = {
|
||||
{"--tls", NULL, OPT_FLAG, offsetof(Config, use_tls)},
|
||||
{"--backup", NULL, OPT_FLAG, offsetof(Config, backup)},
|
||||
{"--stats", NULL, OPT_FLAG, offsetof(Config, stats)},
|
||||
{"--human-readable", "-h", OPT_FLAG, offsetof(Config, human_readable)},
|
||||
{"--partial", NULL, OPT_FLAG, offsetof(Config, partial)},
|
||||
{"--links", "-l", OPT_FLAG, offsetof(Config, follow_symlinks)},
|
||||
{"--copy-links", NULL, OPT_FLAG, offsetof(Config, copy_links)},
|
||||
|
||||
+51
-13
@@ -31,6 +31,14 @@
|
||||
/* Forward declaration for progress-reporting thread used in multithreaded send. */
|
||||
static int progress_thread_fn(void* arg);
|
||||
|
||||
static const char* display_bytes(unsigned long long bytes, bool human_readable, char* buffer,
|
||||
size_t buffer_size) {
|
||||
if (human_readable && format_human_bytes(bytes, buffer, buffer_size))
|
||||
return buffer;
|
||||
snprintf(buffer, buffer_size, "%.1f MB", bytes / 1048576.0);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static ScannerOptions scanner_options_from_config(const Config* config, int num_threads) {
|
||||
ScannerOptions options = {
|
||||
config->use_metadata, config->chunk_size, config->exclude_patterns,
|
||||
@@ -219,20 +227,31 @@ static int send_dry_run_manifest(const Config* config) {
|
||||
Chunk* chunk;
|
||||
int file_count = 0;
|
||||
unsigned long long total_bytes = 0;
|
||||
char size_buffer[32];
|
||||
if (!config->quiet)
|
||||
printf("Dry run: files to be transferred\n");
|
||||
while ((chunk = directory_scanner_next(scanner)) != NULL) {
|
||||
for (int i = 0; i < chunk->element_count; i++) {
|
||||
if (!config->quiet)
|
||||
printf(" %s (%zu bytes)\n", chunk->items[i]->path, chunk->items[i]->data->size);
|
||||
if (!config->quiet) {
|
||||
if (config->human_readable)
|
||||
printf(" %s (%s)\n", chunk->items[i]->path,
|
||||
display_bytes(chunk->items[i]->data->size, true, size_buffer, sizeof(size_buffer)));
|
||||
else
|
||||
printf(" %s (%zu bytes)\n", chunk->items[i]->path, chunk->items[i]->data->size);
|
||||
}
|
||||
total_bytes += chunk->items[i]->data->size;
|
||||
file_count++;
|
||||
}
|
||||
chunk_destroy(chunk);
|
||||
}
|
||||
directory_scanner_destroy(scanner);
|
||||
if (!config->quiet)
|
||||
printf("Total: %d files, %.1f MB\n", file_count, total_bytes / 1048576.0);
|
||||
if (!config->quiet) {
|
||||
if (config->human_readable)
|
||||
printf("Total: %d files, %s\n", file_count,
|
||||
display_bytes(total_bytes, true, size_buffer, sizeof(size_buffer)));
|
||||
else
|
||||
printf("Total: %d files, %.1f MB\n", file_count, total_bytes / 1048576.0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -659,10 +678,20 @@ static int load_files_multithreaded(void* pipeline_context) {
|
||||
line (e.g. "Done.\n") or is "" for in-place refresh. Shared by the
|
||||
single-threaded loop and the multithreaded progress thread. */
|
||||
static void print_transfer_progress(unsigned long long total_bytes, time_t start,
|
||||
const char* suffix) {
|
||||
const char* suffix, bool human_readable) {
|
||||
double elapsed = difftime(time(NULL), start);
|
||||
double rate = elapsed > 0.0 ? total_bytes / (1048576.0 * elapsed) : 0.0;
|
||||
fprintf(stderr, "\rSent %.1f MB (%.1f MB/s) %s", total_bytes / 1048576.0, rate, suffix);
|
||||
if (human_readable) {
|
||||
char total_buffer[32];
|
||||
char rate_buffer[32];
|
||||
fprintf(stderr, "\rSent %s (%s/s) %s",
|
||||
display_bytes(total_bytes, true, total_buffer, sizeof(total_buffer)),
|
||||
display_bytes((unsigned long long)(rate * 1048576.0), true, rate_buffer,
|
||||
sizeof(rate_buffer)),
|
||||
suffix);
|
||||
} else {
|
||||
fprintf(stderr, "\rSent %.1f MB (%.1f MB/s) %s", total_bytes / 1048576.0, rate, suffix);
|
||||
}
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
@@ -680,14 +709,14 @@ static int progress_thread_fn(void* arg) {
|
||||
mtx_unlock(&context->mutex_progress);
|
||||
|
||||
if (done) {
|
||||
print_transfer_progress(total, start, "Done.\n");
|
||||
print_transfer_progress(total, start, "Done.\n", context->config->human_readable);
|
||||
break;
|
||||
}
|
||||
|
||||
time_t now = time(NULL);
|
||||
if (now - last_progress >= 1) {
|
||||
last_progress = now;
|
||||
print_transfer_progress(total, start, "");
|
||||
print_transfer_progress(total, start, "", context->config->human_readable);
|
||||
}
|
||||
|
||||
struct timespec ts = {0, 100 * 1000000L}; /* 100 ms */
|
||||
@@ -765,12 +794,12 @@ int send_files(Config* config) {
|
||||
manifest = NULL;
|
||||
break;
|
||||
}
|
||||
total_bytes += chunk_bytes;
|
||||
if (config->show_progress && !config->quiet) {
|
||||
total_bytes += chunk_bytes;
|
||||
time_t now = time(NULL);
|
||||
if (now - last_progress >= 1) {
|
||||
last_progress = now;
|
||||
print_transfer_progress(total_bytes, start, "");
|
||||
print_transfer_progress(total_bytes, start, "", config->human_readable);
|
||||
}
|
||||
}
|
||||
chunk_destroy(current_chunk);
|
||||
@@ -790,12 +819,21 @@ int send_files(Config* config) {
|
||||
if (ok)
|
||||
remove_transferred_sources(config, remove_sources);
|
||||
if (config->show_progress && !config->quiet)
|
||||
print_transfer_progress(total_bytes, start, "Done.\n");
|
||||
print_transfer_progress(total_bytes, start, "Done.\n", config->human_readable);
|
||||
if (config->stats && !config->quiet) {
|
||||
double elapsed_total = difftime(time(NULL), start);
|
||||
double rate = elapsed_total > 0 ? total_bytes / (1048576.0 * elapsed_total) : 0;
|
||||
fprintf(stderr, "Stats: %d files, %.1f MB, %.1f MB/s\n", total_files, total_bytes / 1048576.0,
|
||||
rate);
|
||||
if (config->human_readable) {
|
||||
char total_buffer[32];
|
||||
char rate_buffer[32];
|
||||
fprintf(stderr, "Stats: %d files, %s, %s/s\n", total_files,
|
||||
display_bytes(total_bytes, true, total_buffer, sizeof(total_buffer)),
|
||||
display_bytes((unsigned long long)(rate * 1048576.0), true, rate_buffer,
|
||||
sizeof(rate_buffer)));
|
||||
} else {
|
||||
fprintf(stderr, "Stats: %d files, %.1f MB, %.1f MB/s\n", total_files, total_bytes / 1048576.0,
|
||||
rate);
|
||||
}
|
||||
}
|
||||
ret = ok ? 0 : 1;
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ void print_usage(void) {
|
||||
printf(" --backup-dir <dir> Directory for backups (requires --backup)\n");
|
||||
printf(" --suffix <str> Backup suffix (default: ~)\n");
|
||||
printf(" --stats Print transfer statistics at end\n");
|
||||
printf(" -h, --human-readable Print byte sizes in human-readable form\n");
|
||||
printf(" --max-depth <n> Maximum directory depth (0=unlimited)\n");
|
||||
printf(" --log-file <path> Write log messages to file\n");
|
||||
printf(" --partial Keep partial files on interrupted transfer\n");
|
||||
|
||||
Reference in New Issue
Block a user