← back to Cli Printing Press
fix(cli): honor explicit --output flag in generate (#281)
6bbae936a0504dabab1febd4d00d3debeeaf50e6 · 2026-04-25 01:58:20 -0700 · Trevin Chow
The post-generate rename block at internal/cli/root.go:424 ran
unconditionally, comparing the output directory's basename against
the spec-derived API name and forcing them to match. The
explicitOutput flag was already computed nine lines earlier (and
correctly consulted by claimOrForce) but never gated the rename.
Skip the rename when --output is supplied so the caller's chosen
path is authoritative. Default-path runs still normalize to the
spec-derived slot for pipeline.DefaultOutputDir callers.
Reported in #275 (F-1).
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files touched
M internal/cli/generate_test.goM internal/cli/root.go
Diff
commit 6bbae936a0504dabab1febd4d00d3debeeaf50e6
Author: Trevin Chow <trevin@trevinchow.com>
Date: Sat Apr 25 01:58:20 2026 -0700
fix(cli): honor explicit --output flag in generate (#281)
The post-generate rename block at internal/cli/root.go:424 ran
unconditionally, comparing the output directory's basename against
the spec-derived API name and forcing them to match. The
explicitOutput flag was already computed nine lines earlier (and
correctly consulted by claimOrForce) but never gated the rename.
Skip the rename when --output is supplied so the caller's chosen
path is authoritative. Default-path runs still normalize to the
spec-derived slot for pipeline.DefaultOutputDir callers.
Reported in #275 (F-1).
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
internal/cli/generate_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++
internal/cli/root.go | 26 ++++++++++++++------------
2 files changed, 57 insertions(+), 12 deletions(-)
diff --git a/internal/cli/generate_test.go b/internal/cli/generate_test.go
index 3982989c..e35ed600 100644
--- a/internal/cli/generate_test.go
+++ b/internal/cli/generate_test.go
@@ -584,3 +584,46 @@ func TestGenerateCmdRejectsTrafficAnalysisWithPlan(t *testing.T) {
require.Error(t, err)
assert.Contains(t, err.Error(), "--traffic-analysis cannot be used with --plan")
}
+
+func TestGenerateCmdHonorsExplicitOutput(t *testing.T) {
+ t.Parallel()
+
+ dir := t.TempDir()
+ specPath := filepath.Join(dir, "spec.yaml")
+ outputDir := filepath.Join(dir, "user-chosen-path")
+ derivedDir := filepath.Join(dir, "explicitoutput")
+
+ require.NoError(t, os.WriteFile(specPath, []byte(`name: explicitoutput
+description: Explicit output API
+version: 0.1.0
+base_url: https://api.example.com
+auth:
+ type: none
+config:
+ format: toml
+ path: ~/.config/explicitoutput-pp-cli/config.toml
+resources:
+ items:
+ description: Manage items
+ endpoints:
+ list:
+ method: GET
+ path: /items
+ description: List items
+`), 0o644))
+
+ cmd := newGenerateCmd()
+ cmd.SetArgs([]string{
+ "--spec", specPath,
+ "--output", outputDir,
+ "--validate=false",
+ "--force",
+ })
+
+ require.NoError(t, cmd.Execute())
+
+ assert.FileExists(t, filepath.Join(outputDir, "go.mod"),
+ "generated files should land at the user-supplied --output path")
+ assert.NoDirExists(t, derivedDir,
+ "the spec-derived directory must not be created when --output is explicit")
+}
diff --git a/internal/cli/root.go b/internal/cli/root.go
index df67b857..4a942e7b 100644
--- a/internal/cli/root.go
+++ b/internal/cli/root.go
@@ -421,18 +421,20 @@ func newGenerateCmd() *cobra.Command {
}
}
- // Rename output directory to match the derived CLI name if they differ.
- // This prevents mismatches when the caller passes a directory name
- // that doesn't match what the generator derives from the spec title
- // (e.g., --output .../calcom-pp-cli but spec title "Cal.com" derives "cal-com-pp-cli").
- derivedDir := apiSpec.Name
- currentBase := filepath.Base(absOut)
- if currentBase != derivedDir {
- finalPath := filepath.Join(filepath.Dir(absOut), derivedDir)
- if err := os.Rename(absOut, finalPath); err != nil {
- fmt.Fprintf(os.Stderr, "warning: could not rename output dir from %s to %s: %v\n", currentBase, derivedDir, err)
- } else {
- absOut = finalPath
+ // When --output was not explicitly supplied, normalize the output
+ // directory to the spec-derived name so default-path runs land in the
+ // expected slot (e.g., spec title "Cal.com" derives "cal-com-pp-cli").
+ // When --output is explicit, the caller's chosen path is authoritative.
+ if !explicitOutput {
+ derivedDir := apiSpec.Name
+ currentBase := filepath.Base(absOut)
+ if currentBase != derivedDir {
+ finalPath := filepath.Join(filepath.Dir(absOut), derivedDir)
+ if err := os.Rename(absOut, finalPath); err != nil {
+ fmt.Fprintf(os.Stderr, "warning: could not rename output dir from %s to %s: %v\n", currentBase, derivedDir, err)
+ } else {
+ absOut = finalPath
+ }
}
}
← 55114c4e fix(cli): treat access-denied sync errors as warnings (#274)
·
back to Cli Printing Press
·
fix(cli): dedup colliding flag identifiers in generated comm 72a84a88 →