From b0f8dfb409d107dce94fe607d243f9b0d6deac09 Mon Sep 17 00:00:00 2001 From: pagran Date: Thu, 9 Feb 2023 14:45:51 +0100 Subject: [PATCH] prevent "git apply" from walking parent directories Even when setting git's current directory to a temporary directory, it could find a git repository in a parent directory and still malfunction. Use the --git-dir flag to ensure that walking doesn't happen at all. While here, ensure that "git apply" is always applying our patches, and add a regression test to linker.txtar when not testing with -short. --- internal/linker/linker.go | 15 +++++++++++++-- testdata/script/linker.txtar | 3 +++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/internal/linker/linker.go b/internal/linker/linker.go index b63e3fd..80281b5 100644 --- a/internal/linker/linker.go +++ b/internal/linker/linker.go @@ -15,6 +15,7 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "runtime" "github.com/bluekeyes/go-gitdiff/gitdiff" @@ -119,12 +120,22 @@ func applyPatches(srcDir, workingDir string, modFiles map[string]bool, patches [ } } - cmd := exec.Command("git", "apply") + // If one of parent folders of workingDir contains repository, set current directory is not enough because git + // by default treats workingDir as a subfolder of repository, so it will break git apply. Adding --git-dir flag blocks this behavior. + cmd := exec.Command("git", "--git-dir", workingDir, "apply", "--verbose") cmd.Dir = workingDir cmd.Stdin = bytes.NewReader(bytes.Join(patches, []byte("\n"))) - if err := cmd.Run(); err != nil { + out, err := cmd.CombinedOutput() + if err != nil { return nil, err } + + // Running git without errors does not guarantee that all patches have been applied. + // Make sure that all passed patches have been applied correctly. + rx := regexp.MustCompile(`(?m)^Applied patch .+ cleanly\.$`) + if appliedPatches := len(rx.FindAllIndex(out, -1)); appliedPatches != len(patches) { + return nil, fmt.Errorf("expected %d applied patches, actually %d:\n\n%s", len(patches), appliedPatches, string(out)) + } return mod, nil } diff --git a/testdata/script/linker.txtar b/testdata/script/linker.txtar index e802044..20d40d4 100644 --- a/testdata/script/linker.txtar +++ b/testdata/script/linker.txtar @@ -1,3 +1,6 @@ +[!short] [exec:git] exec git init -q +[!short] [exec:git] env GARBLE_CACHE_DIR=$WORK/linker-cache + garble build exec ./main ! cmp stderr main.stderr