diff --git a/internal/cli/entry_test.go b/internal/cli/entry_test.go index 7fd3605..b27ea7e 100644 --- a/internal/cli/entry_test.go +++ b/internal/cli/entry_test.go @@ -1347,20 +1347,22 @@ func TestGenerateDefaultOutput(t *testing.T) { func TestGenerateSeveralPathsDefaultOutput(t *testing.T) { root := t.TempDir() fs := afero.NewOsFs() - require.NoError(t, fs.MkdirAll(filepath.Join(root, "first"), 0o750)) - require.NoError(t, fs.MkdirAll(filepath.Join(root, "second"), 0o750)) - writeTestFile(t, fs, filepath.Join(root, "first", "one.txt"), "1") - writeTestFile(t, fs, filepath.Join(root, "second", "two.txt"), "2") + dirs := []string{"first", "second"} + + for _, dir := range dirs { + require.NoError(t, fs.MkdirAll(filepath.Join(root, dir), 0o750)) + writeTestFile(t, fs, filepath.Join(root, dir, dir+".txt"), dir) + } t.Chdir(root) - opts := testOpts([]string{testApp, cmdGenerate, "-q", "first", "second"}, fs) + opts := testOpts(append([]string{testApp, cmdGenerate, "-q"}, dirs...), fs) require.Equal(t, 0, runCLI(opts), "stderr: %s", testStderr(t, opts)) - assert.ElementsMatch(t, []string{"one.txt", "two.txt"}, + assert.ElementsMatch(t, []string{"first.txt", "second.txt"}, manifestPaths(t, fs, filepath.Join(root, defaultManifestName))) - for _, dir := range []string{"first", "second"} { + for _, dir := range dirs { exists, err := afero.Exists(fs, filepath.Join(root, dir, defaultManifestName)) require.NoError(t, err) assert.False(t, exists, "index.mf written in %s", dir) diff --git a/internal/cli/gen.go b/internal/cli/gen.go index 3c33e3a..4ea3e36 100644 --- a/internal/cli/gen.go +++ b/internal/cli/gen.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "io" "os" "os/signal" "path/filepath" @@ -235,6 +236,35 @@ func (mfa *CLIApp) runEnumeratePhase(cmd *cli.Command, s *mfer.Scanner) error { return nil } +// runScanPhase reads the enumerated files and writes the manifest to out, +// with optional progress reporting. +func (mfa *CLIApp) runScanPhase( + ctx context.Context, cmd *cli.Command, s *mfer.Scanner, out io.Writer, +) error { + var ( + scanProgress chan mfer.ScanStatus + scanWg sync.WaitGroup + ) + + if cmd.Bool("progress") { + scanProgress = make(chan mfer.ScanStatus, 1) + + scanWg.Add(1) + + go reportScanProgress(scanProgress, &scanWg) + } + + err := s.ToManifest(ctx, out, scanProgress) + + scanWg.Wait() + + if err != nil { + return fmt.Errorf("generate manifest: %w", err) + } + + return nil +} + func (mfa *CLIApp) generateManifestOperation( ctx context.Context, cmd *cli.Command, ) error { @@ -253,8 +283,6 @@ func (mfa *CLIApp) generateManifestOperation( return err } - showProgress := cmd.Bool("progress") - // Check if output file exists if exists, _ := afero.Exists(mfa.Fs, outputPath); exists && !cmd.Bool("force") { return fmt.Errorf("output file %s %w", outputPath, errOutputExists) @@ -286,25 +314,9 @@ func (mfa *CLIApp) generateManifestOperation( }() // Phase 2: Scan - read file contents and generate manifest - var ( - scanProgress chan mfer.ScanStatus - scanWg sync.WaitGroup - ) - - if showProgress { - scanProgress = make(chan mfer.ScanStatus, 1) - - scanWg.Add(1) - - go reportScanProgress(scanProgress, &scanWg) - } - - err = s.ToManifest(ctx, outFile, scanProgress) - - scanWg.Wait() - + err = mfa.runScanPhase(ctx, cmd, s, outFile) if err != nil { - return fmt.Errorf("generate manifest: %w", err) + return err } // Close file before rename to ensure all data is flushed