@@ -276,6 +276,15 @@ The test runner includes automatic result persistence: |
||
| 276 | 276 |
|
| 277 | 277 |
--- |
| 278 | 278 |
|
| 279 |
+### 2026-05-18 08:40 - Report Table Cleanup |
|
| 280 |
+ |
|
| 281 |
+- Aligned final report labels with a shared formatter. |
|
| 282 |
+- Removed file-per-time throughput and average-per-file metrics from the final report. |
|
| 283 |
+- Kept elapsed time and data throughput in `MB/sec`, which better reflects transfer performance. |
|
| 284 |
+- Made test report cleanup portable on macOS by removing GNU `find -printf` and negative `head` usage. |
|
| 285 |
+ |
|
| 286 |
+--- |
|
| 287 |
+ |
|
| 279 | 288 |
### 2026-05-13 21:10 - Critical Data Loss Incident + Hardening |
| 280 | 289 |
|
| 281 | 290 |
- Observed incident: running with explicit source on a problematic/near-full card led to writes on source media and source content removal without strong post-write confirmation. |
@@ -207,18 +207,72 @@ get_file_size() {
|
||
| 207 | 207 |
fi |
| 208 | 208 |
} |
| 209 | 209 |
|
| 210 |
-# (Removed checksum/prefix/conflict helper functions to revert to pre-conflict-resolution behavior) |
|
| 211 |
- |
|
| 212 | 210 |
# Safe move/copy helpers: filter out benign "set flags (was: ...): Operation not supported" |
| 213 | 211 |
# which appears when moving files onto filesystems that don't support BSD file flags |
| 214 | 212 |
# (macOS mv may try to preserve flags and print this warning while still succeeding). |
| 215 | 213 |
safe_mv() {
|
| 216 | 214 |
local src="$1" dst="$2" |
| 215 |
+ if [[ -e "$dst" ]]; then |
|
| 216 |
+ log_message "Refusing to overwrite existing destination: $dst" "ERROR" |
|
| 217 |
+ return 1 |
|
| 218 |
+ fi |
|
| 217 | 219 |
# Redirect stderr through a filter that removes the known benign message |
| 218 | 220 |
mv "$src" "$dst" 2> >(grep -v "set flags (was:" >&2) |
| 219 | 221 |
return $? |
| 220 | 222 |
} |
| 221 | 223 |
|
| 224 |
+safe_cp() {
|
|
| 225 |
+ local src="$1" dst="$2" |
|
| 226 |
+ if [[ -e "$dst" ]]; then |
|
| 227 |
+ log_message "Refusing to overwrite existing destination: $dst" "ERROR" |
|
| 228 |
+ return 1 |
|
| 229 |
+ fi |
|
| 230 |
+ cp -p "$src" "$dst" 2> >(grep -v "set flags (was:" >&2) |
|
| 231 |
+ return $? |
|
| 232 |
+} |
|
| 233 |
+ |
|
| 234 |
+ensure_unique_destination_path() {
|
|
| 235 |
+ local desired_path="$1" |
|
| 236 |
+ |
|
| 237 |
+ if [[ -z "$desired_path" ]]; then |
|
| 238 |
+ return 1 |
|
| 239 |
+ fi |
|
| 240 |
+ |
|
| 241 |
+ if ! destination_path_unavailable "$desired_path"; then |
|
| 242 |
+ echo "$desired_path" |
|
| 243 |
+ return 0 |
|
| 244 |
+ fi |
|
| 245 |
+ |
|
| 246 |
+ local dir_path filename ext stem candidate |
|
| 247 |
+ dir_path=$(dirname "$desired_path") |
|
| 248 |
+ filename=$(basename "$desired_path") |
|
| 249 |
+ |
|
| 250 |
+ if [[ "$filename" == *.* ]]; then |
|
| 251 |
+ ext="${filename##*.}"
|
|
| 252 |
+ stem="${filename%.*}"
|
|
| 253 |
+ else |
|
| 254 |
+ ext="" |
|
| 255 |
+ stem="$filename" |
|
| 256 |
+ fi |
|
| 257 |
+ |
|
| 258 |
+ local i |
|
| 259 |
+ i=1 |
|
| 260 |
+ while [[ $i -le 9999 ]]; do |
|
| 261 |
+ if [[ -n "$ext" ]]; then |
|
| 262 |
+ candidate="$dir_path/${stem}_${i}.${ext}"
|
|
| 263 |
+ else |
|
| 264 |
+ candidate="$dir_path/${stem}_${i}"
|
|
| 265 |
+ fi |
|
| 266 |
+ if ! destination_path_unavailable "$candidate"; then |
|
| 267 |
+ echo "$candidate" |
|
| 268 |
+ return 0 |
|
| 269 |
+ fi |
|
| 270 |
+ i=$((i + 1)) |
|
| 271 |
+ done |
|
| 272 |
+ |
|
| 273 |
+ return 1 |
|
| 274 |
+} |
|
| 275 |
+ |
|
| 222 | 276 |
destination_path_reserved() {
|
| 223 | 277 |
local candidate="$1" |
| 224 | 278 |
local reserved_path |
@@ -647,30 +701,28 @@ format_duration() {
|
||
| 647 | 701 |
fi |
| 648 | 702 |
} |
| 649 | 703 |
|
| 650 |
-format_processing_rate() {
|
|
| 651 |
- local files_count="$1" |
|
| 652 |
- local bytes_count="$2" |
|
| 653 |
- local elapsed_seconds="$3" |
|
| 704 |
+format_data_rate() {
|
|
| 705 |
+ local bytes_count="$1" |
|
| 706 |
+ local elapsed_seconds="$2" |
|
| 654 | 707 |
|
| 655 |
- awk -v files="$files_count" -v bytes="$bytes_count" -v seconds="$elapsed_seconds" ' |
|
| 708 |
+ awk -v bytes="$bytes_count" -v seconds="$elapsed_seconds" ' |
|
| 656 | 709 |
BEGIN {
|
| 657 |
- if (seconds <= 0 || files <= 0) {
|
|
| 710 |
+ if (seconds <= 0 || bytes <= 0) {
|
|
| 658 | 711 |
exit |
| 659 | 712 |
} |
| 660 | 713 |
|
| 661 |
- files_per_second = files / seconds |
|
| 662 |
- files_per_minute = files * 60 / seconds |
|
| 663 | 714 |
mb_per_second = bytes / seconds / 1048576 |
| 664 |
- |
|
| 665 |
- if (files_per_second >= 1) {
|
|
| 666 |
- printf "%.2f files/sec, %.2f MB/sec", files_per_second, mb_per_second |
|
| 667 |
- } else {
|
|
| 668 |
- printf "%.2f files/min, %.2f MB/sec", files_per_minute, mb_per_second |
|
| 669 |
- } |
|
| 715 |
+ printf "%.2f MB/sec", mb_per_second |
|
| 670 | 716 |
} |
| 671 | 717 |
' |
| 672 | 718 |
} |
| 673 | 719 |
|
| 720 |
+report_line() {
|
|
| 721 |
+ local label="$1" |
|
| 722 |
+ local value="$2" |
|
| 723 |
+ printf " %-24s %s\n" "$label" "$value" |
|
| 724 |
+} |
|
| 725 |
+ |
|
| 674 | 726 |
# Function to extract date from file |
| 675 | 727 |
extract_file_date() {
|
| 676 | 728 |
local file="$1" |
@@ -1171,13 +1223,31 @@ show_report() {
|
||
| 1171 | 1223 |
print_color "$GREEN" " PROCESSING REPORT" |
| 1172 | 1224 |
print_color "$GREEN" "==========================================" |
| 1173 | 1225 |
echo "" |
| 1174 |
- |
|
| 1226 |
+ |
|
| 1227 |
+ echo "Files Summary:" |
|
| 1228 |
+ report_line "Total files found:" "$TOTAL_FILES" |
|
| 1229 |
+ report_line "Successfully processed:" "$PROCESSED_FILES" |
|
| 1230 |
+ report_line "Skipped:" "$SKIPPED_FILES" |
|
| 1231 |
+ report_line "Errors:" "$ERROR_FILES" |
|
| 1232 |
+ echo "" |
|
| 1233 |
+ |
|
| 1175 | 1234 |
echo "Size Summary:" |
| 1176 |
- printf " %-22s %s\n" "Total size found:" "$(format_size $TOTAL_SIZE)" |
|
| 1177 |
- printf " %-22s %s\n" "Successfully processed:" "$(format_size $PROCESSED_SIZE)" |
|
| 1178 |
- |
|
| 1235 |
+ report_line "Total size found:" "$(format_size $TOTAL_SIZE)" |
|
| 1236 |
+ report_line "Successfully processed:" "$(format_size $PROCESSED_SIZE)" |
|
| 1179 | 1237 |
echo "" |
| 1180 |
- |
|
| 1238 |
+ |
|
| 1239 |
+ echo "Time Summary:" |
|
| 1240 |
+ report_line "Time elapsed:" "$(printf "%02d:%02d:%02d" $hours $minutes $seconds)" |
|
| 1241 |
+ if [[ $elapsed_time -gt 0 && $PROCESSED_SIZE -gt 0 ]]; then |
|
| 1242 |
+ local data_rate |
|
| 1243 |
+ data_rate=$(format_data_rate "$PROCESSED_SIZE" "$elapsed_time") |
|
| 1244 |
+ if [[ -n "$data_rate" ]]; then |
|
| 1245 |
+ report_line "Data rate:" "$data_rate" |
|
| 1246 |
+ fi |
|
| 1247 |
+ fi |
|
| 1248 |
+ |
|
| 1249 |
+ echo "" |
|
| 1250 |
+ |
|
| 1181 | 1251 |
if [[ $DRY_RUN -eq 1 ]]; then |
| 1182 | 1252 |
print_color "$YELLOW" "DRY RUN MODE - No files were actually moved/copied" |
| 1183 | 1253 |
elif [[ $KEEP_ORIGINALS -eq 1 ]]; then |
@@ -206,19 +206,29 @@ EOF |
||
| 206 | 206 |
cleanup_old_reports() {
|
| 207 | 207 |
if [[ -d "$TEST_REPORTS_DIR" ]]; then |
| 208 | 208 |
# Count total reports |
| 209 |
- local total_reports=$(find "$TEST_REPORTS_DIR" -name "*.md" | wc -l) |
|
| 209 |
+ local total_reports |
|
| 210 |
+ total_reports=$(find "$TEST_REPORTS_DIR" -name "*.md" | wc -l | tr -d ' ') |
|
| 210 | 211 |
|
| 211 | 212 |
if [[ $total_reports -gt 10 ]]; then |
| 212 | 213 |
print_color "$BLUE" "Cleaning up old test reports (keeping last 10)..." |
| 213 | 214 |
|
| 214 |
- # Find and remove oldest reports, keeping the 10 most recent |
|
| 215 |
- find "$TEST_REPORTS_DIR" -name "*.md" -type f -printf '%T@ %p\n' | \ |
|
| 216 |
- sort -n | \ |
|
| 217 |
- head -n -$((10)) | \ |
|
| 218 |
- cut -d' ' -f2- | \ |
|
| 219 |
- xargs -r rm |
|
| 220 |
- |
|
| 221 |
- local remaining=$(find "$TEST_REPORTS_DIR" -name "*.md" | wc -l) |
|
| 215 |
+ local remove_count |
|
| 216 |
+ remove_count=$((total_reports - 10)) |
|
| 217 |
+ |
|
| 218 |
+ find "$TEST_REPORTS_DIR" -name "*.md" -type f | while IFS= read -r report_file; do |
|
| 219 |
+ local report_mtime |
|
| 220 |
+ if report_mtime=$(stat -f %m "$report_file" 2>/dev/null); then |
|
| 221 |
+ : |
|
| 222 |
+ else |
|
| 223 |
+ report_mtime=$(stat -c %Y "$report_file" 2>/dev/null || echo 0) |
|
| 224 |
+ fi |
|
| 225 |
+ printf '%s\t%s\n' "$report_mtime" "$report_file" |
|
| 226 |
+ done | sort -n | head -n "$remove_count" | cut -f2- | while IFS= read -r old_report; do |
|
| 227 |
+ rm -f "$old_report" |
|
| 228 |
+ done |
|
| 229 |
+ |
|
| 230 |
+ local remaining |
|
| 231 |
+ remaining=$(find "$TEST_REPORTS_DIR" -name "*.md" | wc -l | tr -d ' ') |
|
| 222 | 232 |
print_color "$GREEN" "Kept $remaining most recent test reports" |
| 223 | 233 |
fi |
| 224 | 234 |
fi |