From 03d24ef984a746ff40855d9466890f9cbdcac849 Mon Sep 17 00:00:00 2001 From: Adam Manwaring 'Pants Date: Mon, 15 May 2023 16:40:49 -0600 Subject: [PATCH] Search in parent directories if mage files are not found --- mage/main.go | 68 ++++++++++++------- mage/main_test.go | 48 +++++++++++++ .../sub_folder/sub_folder2/mage_helpers.go | 6 ++ .../sub_folder/sub_folder2/magefile.go | 6 ++ 4 files changed, 103 insertions(+), 25 deletions(-) create mode 100644 mage/testdata/with_magefiles_folder/sub_folder/sub_folder2/mage_helpers.go create mode 100644 mage/testdata/with_magefiles_folder/sub_folder/sub_folder2/magefile.go diff --git a/mage/main.go b/mage/main.go index 0062bd35..d9d9f984 100644 --- a/mage/main.go +++ b/mage/main.go @@ -319,44 +319,62 @@ func Invoke(inv Invocation) int { if inv.Dir == "" { inv.Dir = dotDirectory } + inv.Dir, _ = filepath.Abs(inv.Dir) if inv.WorkDir == "" { inv.WorkDir = inv.Dir } - magefilesDir := filepath.Join(inv.Dir, MagefilesDirName) - // . will be default unless we find a mage folder. - mfSt, err := os.Stat(magefilesDir) - if err == nil { - if mfSt.IsDir() { - stderrBuf := &bytes.Buffer{} - originalDir := inv.Dir - inv.Dir = magefilesDir // preemptive assignment - // TODO: Remove this fallback and the above Magefiles invocation when the bw compatibility is removed. - files, err := Magefiles(originalDir, inv.GOOS, inv.GOARCH, inv.GoCmd, stderrBuf, false, inv.Debug) - if err == nil { - if len(files) != 0 { - errlog.Println("[WARNING] You have both a magefiles directory and mage files in the " + - "current directory, in future versions the files will be ignored in favor of the directory") - inv.Dir = originalDir + var ( + files []string + err error + errMsg string + ) + + for len(files) == 0 && len(inv.Dir) > 1 { + magefilesDir := filepath.Join(inv.Dir, MagefilesDirName) + // . will be default unless we find a mage folder. + mfSt, err := os.Stat(magefilesDir) + if err == nil { + if mfSt.IsDir() { + stderrBuf := &bytes.Buffer{} + originalDir := inv.Dir + inv.Dir = magefilesDir // preemptive assignment + // TODO: Remove this fallback and the above Magefiles invocation when the bw compatibility is removed. + files, err := Magefiles(originalDir, inv.GOOS, inv.GOARCH, inv.GoCmd, stderrBuf, false, inv.Debug) + if err == nil { + if len(files) != 0 { + errlog.Println("[WARNING] You have both a magefiles directory and mage files in the " + + "current directory, in future versions the files will be ignored in favor of the directory") + inv.Dir = originalDir + } } } } - } - if inv.CacheDir == "" { - inv.CacheDir = mg.CacheDir() - } + files, err = Magefiles(inv.Dir, inv.GOOS, inv.GOARCH, inv.GoCmd, inv.Stderr, inv.UsesMagefiles(), inv.Debug) + if err != nil { + errMsg = fmt.Sprintf("Error determining list of magefiles: %s", err) + inv.Dir = filepath.Dir(inv.Dir) + files = []string{} + continue + } - files, err := Magefiles(inv.Dir, inv.GOOS, inv.GOARCH, inv.GoCmd, inv.Stderr, inv.UsesMagefiles(), inv.Debug) - if err != nil { - errlog.Println("Error determining list of magefiles:", err) - return 1 + if len(files) == 0 { + errMsg = "No .go files marked with the mage build tag in this directory or any parent directory." + inv.Dir = filepath.Dir(inv.Dir) + files = []string{} + continue + } } - if len(files) == 0 { - errlog.Println("No .go files marked with the mage build tag in this directory.") + errlog.Println(errMsg) return 1 } debug.Printf("found magefiles: %s", strings.Join(files, ", ")) + + if inv.CacheDir == "" { + inv.CacheDir = mg.CacheDir() + } + exePath := inv.CompileOut if inv.CompileOut == "" { exePath, err = ExeName(inv.GoCmd, inv.CacheDir, files) diff --git a/mage/main_test.go b/mage/main_test.go index b722d842..6f4e3c95 100644 --- a/mage/main_test.go +++ b/mage/main_test.go @@ -375,6 +375,54 @@ func TestMagefilesFolder(t *testing.T) { } } +func TestFindFilesInParents(t *testing.T) { + resetTerm() + wd, err := os.Getwd() + t.Log(wd) + if err != nil { + t.Fatalf("finding current working directory: %v", err) + } + if err := os.Chdir("testdata/with_magefiles_folder/sub_folder"); err != nil { + t.Fatalf("changing to magefolders tests data: %v", err) + } + // restore previous state + defer os.Chdir(wd) + + stderr := &bytes.Buffer{} + stdout := &bytes.Buffer{} + inv := Invocation{ + Dir: "", + Stdout: stdout, + Stderr: stderr, + List: true, + } + // get magefiles even when in subfolder + code := Invoke(inv) + if code != 0 { + t.Errorf("expected to exit with code 0, but got %v, stderr: %s", code, stderr) + } + expected := "Targets:\n build \n" + actual := stdout.String() + if actual != expected { + t.Fatalf("expected %q but got %q", expected, actual) + } + stdout.Truncate(0) // clear buffer for next test case + + // ignore parent magefiles when subfolder has magefiles + if err := os.Chdir("sub_folder2"); err != nil { + t.Fatalf("changing to magefolders tests data: %v", err) + } + code = Invoke(inv) + if code != 0 { + t.Errorf("expected to exit with code 0, but got %v, stderr: %s", code, stderr) + } + expected = "Targets:\n subBuild \n" + actual = stdout.String() + if actual != expected { + t.Fatalf("expected %q but got %q", expected, actual) + } +} + func TestMagefilesFolderMixedWithMagefiles(t *testing.T) { resetTerm() wd, err := os.Getwd() diff --git a/mage/testdata/with_magefiles_folder/sub_folder/sub_folder2/mage_helpers.go b/mage/testdata/with_magefiles_folder/sub_folder/sub_folder2/mage_helpers.go new file mode 100644 index 00000000..e4b8872f --- /dev/null +++ b/mage/testdata/with_magefiles_folder/sub_folder/sub_folder2/mage_helpers.go @@ -0,0 +1,6 @@ +//go:build mage +// +build mage + +package main + +func foo() {} diff --git a/mage/testdata/with_magefiles_folder/sub_folder/sub_folder2/magefile.go b/mage/testdata/with_magefiles_folder/sub_folder/sub_folder2/magefile.go new file mode 100644 index 00000000..4d2af1d9 --- /dev/null +++ b/mage/testdata/with_magefiles_folder/sub_folder/sub_folder2/magefile.go @@ -0,0 +1,6 @@ +//go:build mage +// +build mage + +package main + +func SubBuild() {}