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