From 72f3727895e14bc109838dcd522b9053fb55fdfa Mon Sep 17 00:00:00 2001 From: Zack Brady Date: Mon, 17 Aug 2026 23:35:51 -0400 Subject: [PATCH] added workdir flag and env var --- cmd/hauler/cli/store/sync.go | 6 ++++-- internal/flags/cli.go | 2 ++ internal/flags/store.go | 8 ++++++++ pkg/consts/consts.go | 1 + 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/cmd/hauler/cli/store/sync.go b/cmd/hauler/cli/store/sync.go index 37f0e63..2134f21 100644 --- a/cmd/hauler/cli/store/sync.go +++ b/cmd/hauler/cli/store/sync.go @@ -163,12 +163,14 @@ func SyncCmd(ctx context.Context, o *flags.SyncOpts, s *store.Layout, rso *flags if err != nil { return fmt.Errorf("failed to fetch product manifest for [%s]: %w", productName, err) } - err = ExtractCmd(ctx, &flags.ExtractOpts{StoreRootOpts: o.StoreRootOpts, DestinationDir: tempDir}, s, fmt.Sprintf("hauler/%s-manifest.yaml:%s", parts[0], tag)) + // The manifest is output for the user, so it goes to workDir, not tempDir (removed when sync returns). + workDir := flags.ResolveWorkDir(ro) + err = ExtractCmd(ctx, &flags.ExtractOpts{StoreRootOpts: o.StoreRootOpts, DestinationDir: workDir}, s, fmt.Sprintf("hauler/%s-manifest.yaml:%s", parts[0], tag)) if err != nil { return err } fileName := fmt.Sprintf("%s-manifest.yaml", parts[0]) - fi, err := os.Open(filepath.Join(tempDir, fileName)) + fi, err := os.Open(filepath.Join(workDir, fileName)) if err != nil { return err } diff --git a/internal/flags/cli.go b/internal/flags/cli.go index 4bfab7f..800322a 100644 --- a/internal/flags/cli.go +++ b/internal/flags/cli.go @@ -7,6 +7,7 @@ type CliRootOpts struct { HaulerDir string IgnoreErrors bool AuditLevel string + WorkDir string } func AddRootFlags(cmd *cobra.Command, ro *CliRootOpts) { @@ -16,4 +17,5 @@ func AddRootFlags(cmd *cobra.Command, ro *CliRootOpts) { pf.StringVarP(&ro.HaulerDir, "haulerdir", "d", "", "Set the location of the hauler directory (default $HOME/.hauler)") pf.BoolVar(&ro.IgnoreErrors, "ignore-errors", false, "Warn and continue instead of failing on errors, including storing images that failed verification (defaults false)") pf.StringVar(&ro.AuditLevel, "audit-level", "", "Set the audit logging level (none, standard, verbose) (defaults standard)") + pf.StringVarP(&ro.WorkDir, "work-dir", "w", "", "(Optional) Set the directory for output that commands would otherwise write to the current directory (default: current directory)") } diff --git a/internal/flags/store.go b/internal/flags/store.go index 31a09a0..6a10793 100644 --- a/internal/flags/store.go +++ b/internal/flags/store.go @@ -144,3 +144,11 @@ func resolveHaulerDir(ro *CliRootOpts) string { home, _ := os.UserHomeDir() return filepath.Join(home, consts.DefaultHaulerDirName) } + +// ResolveWorkDir returns the configured output dir, or "" to mean the current directory (legacy behavior). +func ResolveWorkDir(ro *CliRootOpts) string { + if ro != nil && ro.WorkDir != "" { + return ro.WorkDir + } + return os.Getenv(consts.HaulerWorkDir) +} diff --git a/pkg/consts/consts.go b/pkg/consts/consts.go index 44f0eba..445e296 100644 --- a/pkg/consts/consts.go +++ b/pkg/consts/consts.go @@ -95,6 +95,7 @@ const ( // environment variables HaulerDir = "HAULER_DIR" HaulerTempDir = "HAULER_TEMP_DIR" + HaulerWorkDir = "HAULER_WORK_DIR" HaulerStoreDir = "HAULER_STORE_DIR" HaulerIgnoreErrors = "HAULER_IGNORE_ERRORS" HaulerRetries = "HAULER_RETRIES"