From f5bd1465d89c0555c37984a655ca8a278eced220 Mon Sep 17 00:00:00 2001 From: Mitar Date: Mon, 20 Dec 2021 23:26:15 +0100 Subject: [PATCH] Add ChangeToFlag to allow changing the current working directory. --- util.go | 19 +++++++++++++++++++ util_test.go | 22 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/util.go b/util.go index 154aebc..aaf7426 100644 --- a/util.go +++ b/util.go @@ -2,6 +2,8 @@ package kong import ( "fmt" + "os" + "reflect" ) // ConfigFlag uses the configured (via kong.Configuration(loader)) configuration loader to load configuration @@ -33,3 +35,20 @@ func (v VersionFlag) BeforeApply(app *Kong, vars Vars) error { app.Exit(0) return nil } + +// ChangeDirFlag changes the current working directory to a path specified by a flag +// early in the parsing process, changing how other flags resolve relative paths. +// +// Use this flag to provide a "git -C" like functionality. +type ChangeDirFlag string + +// Decode is used to create a side effect of changing the current working directory. +func (c ChangeDirFlag) Decode(ctx *DecodeContext) error { + var path string + err := ctx.Scan.PopValueInto("string", &path) + if err != nil { + return err + } + ctx.Value.Target.Set(reflect.ValueOf(ChangeDirFlag(path))) + return os.Chdir(path) +} diff --git a/util_test.go b/util_test.go index 358f43d..b4a1666 100644 --- a/util_test.go +++ b/util_test.go @@ -3,6 +3,7 @@ package kong import ( "io/ioutil" "os" + "path/filepath" "strings" "testing" @@ -42,3 +43,24 @@ func TestVersionFlag(t *testing.T) { require.Equal(t, "0.1.1", strings.TrimSpace(w.String())) require.Equal(t, 0, called) } + +func TestChangeDirFlag(t *testing.T) { + cwd, err := os.Getwd() + require.NoError(t, err) + defer os.Chdir(cwd) // nolint: errcheck + + dir := t.TempDir() + file := filepath.Join(dir, "out.txt") + err = os.WriteFile(file, []byte("foobar"), 0o600) + require.NoError(t, err) + + var cli struct { + ChangeDir ChangeDirFlag `short:"C"` + Path string `arg:"" type:"existingfile"` + } + + p := Must(&cli) + _, err = p.Parse([]string{"-C", dir, "out.txt"}) + require.NoError(t, err) + require.Equal(t, file, cli.Path) +}