From 33f82ebda8acb46d7aea0b0976b11dcaaefcdc7a Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 21 Feb 2026 13:04:30 +0000 Subject: [PATCH] feat(collect): wire streaming pipeline into CLI, update docs Replace ui.NewProgressBar with the Progress interface in CollectLocal, update command help text to describe streaming mode for STIM format, and mark the design document status as Implemented. Co-Authored-By: Claude Opus 4.6 --- cmd/collect_local.go | 18 ++++++++++-------- docs/plans/2026-02-21-borg-upgrade-design.md | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/cmd/collect_local.go b/cmd/collect_local.go index 998b15a..1891f0b 100644 --- a/cmd/collect_local.go +++ b/cmd/collect_local.go @@ -30,9 +30,11 @@ func NewCollectLocalCmd() *CollectLocalCmd { c.Command = cobra.Command{ Use: "local [directory]", Short: "Collect files from a local directory", - Long: `Collect files from a local directory and store them in a DataNode. + Long: `Collect local files into a portable container. -If no directory is specified, the current working directory is used. +For STIM format, uses streaming I/O — memory usage is constant +(~2 MiB) regardless of input directory size. Other formats +(datanode, tim, trix) load files into memory. Examples: borg collect local @@ -55,7 +57,8 @@ Examples: includeHidden, _ := cmd.Flags().GetBool("hidden") respectGitignore, _ := cmd.Flags().GetBool("gitignore") - finalPath, err := CollectLocal(directory, outputFile, format, compression, password, excludes, includeHidden, respectGitignore) + progress := ProgressFromCmd(cmd) + finalPath, err := CollectLocal(directory, outputFile, format, compression, password, excludes, includeHidden, respectGitignore, progress) if err != nil { return err } @@ -78,7 +81,7 @@ func init() { } // CollectLocal collects files from a local directory into a DataNode -func CollectLocal(directory string, outputFile string, format string, compression string, password string, excludes []string, includeHidden bool, respectGitignore bool) (string, error) { +func CollectLocal(directory string, outputFile string, format string, compression string, password string, excludes []string, includeHidden bool, respectGitignore bool, progress ui.Progress) (string, error) { // Validate format if format != "datanode" && format != "tim" && format != "trix" && format != "stim" { return "", fmt.Errorf("invalid format: %s (must be 'datanode', 'tim', 'trix', or 'stim')", format) @@ -129,8 +132,7 @@ func CollectLocal(directory string, outputFile string, format string, compressio dn := datanode.New() var fileCount int - bar := ui.NewProgressBar(-1, "Scanning files") - defer bar.Finish() + progress.Start("collecting " + directory) err = filepath.WalkDir(absDir, func(path string, d fs.DirEntry, err error) error { if err != nil { @@ -186,7 +188,7 @@ func CollectLocal(directory string, outputFile string, format string, compressio // Add to DataNode with forward slashes (tar convention) dn.AddData(filepath.ToSlash(relPath), content) fileCount++ - bar.Describe(fmt.Sprintf("Collected %d files", fileCount)) + progress.Update(int64(fileCount), 0) return nil }) @@ -199,7 +201,7 @@ func CollectLocal(directory string, outputFile string, format string, compressio return "", fmt.Errorf("no files found in %s", directory) } - bar.Describe(fmt.Sprintf("Packaging %d files", fileCount)) + progress.Finish(fmt.Sprintf("collected %d files", fileCount)) // Convert to output format var data []byte diff --git a/docs/plans/2026-02-21-borg-upgrade-design.md b/docs/plans/2026-02-21-borg-upgrade-design.md index 2ad14d6..e3b78e2 100644 --- a/docs/plans/2026-02-21-borg-upgrade-design.md +++ b/docs/plans/2026-02-21-borg-upgrade-design.md @@ -1,7 +1,7 @@ # Borg Production Backup Upgrade — Design Document **Date:** 2026-02-21 -**Status:** Approved +**Status:** Implemented **Approach:** Bottom-Up Refactor ## Problem Statement