From ec1003a33966cd4b3932d7dc9526f3e6d34c4bdc Mon Sep 17 00:00:00 2001 From: elsapet Date: Thu, 17 Oct 2024 16:47:51 +0200 Subject: [PATCH] fix: filenames with spaces in diff scan --- pkg/git/diff.go | 32 ++++++++++++++++++++++++++++---- pkg/git/diff_test.go | 18 ++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/pkg/git/diff.go b/pkg/git/diff.go index 3fa0f5262..d0fb24749 100644 --- a/pkg/git/diff.go +++ b/pkg/git/diff.go @@ -28,6 +28,9 @@ type FilePatch struct { Chunks Chunks } +const SRC_PREFIX = "caf67b1d-c9b7-44ba-9b85-bd94727547af" +const DST_PREFIX = "7dcfe536-96a9-49c5-8b86-7caa3d9e5e9c" + func Diff(rootDir, baseRef string) ([]FilePatch, error) { var result []FilePatch @@ -40,7 +43,8 @@ func Diff(rootDir, baseRef string) ([]FilePatch, error) { "--first-parent", "--find-renames", "--break-rewrites", - "--no-prefix", + "--src-prefix=" + SRC_PREFIX, + "--dst-prefix=" + DST_PREFIX, "--no-color", baseRef, "--", @@ -113,13 +117,13 @@ func parseDiff(scanner *linescanner.Scanner) ([]FilePatch, error) { } func parseDiffHeader(value string) (string, string, error) { - parts := strings.Split(value, " ") - fromPath, err := unquoteFilename(parts[2]) + rawFromPath, rawToPath := splitPaths(value) + fromPath, err := unquoteFilename(rawFromPath) if err != nil { return "", "", fmt.Errorf("error parsing header 'from' path: %w", err) } - toPath, err := unquoteFilename(parts[3]) + toPath, err := unquoteFilename(rawToPath) if err != nil { return "", "", fmt.Errorf("error parsing header 'to' path: %w", err) } @@ -127,6 +131,26 @@ func parseDiffHeader(value string) (string, string, error) { return fromPath, toPath, nil } +func splitPaths(value string) (fromPath string, toPath string) { + split1 := strings.Split(value, SRC_PREFIX)[1] + split2 := strings.Split(split1, DST_PREFIX) + + fromPath = strings.TrimSpace(split2[0]) + toPath = strings.TrimSpace(split2[1]) + + // handle trailing whitespaces and missing quotation marks + // e.g. `foo\\t.txt \"` + if strings.Contains(fromPath, "\"") { + fromPath = "\"" + strings.TrimSpace(strings.ReplaceAll(fromPath, "\"", "")) + "\"" + } + + if strings.Contains(toPath, "\"") { + toPath = "\"" + strings.ReplaceAll(toPath, "\"", "") + "\"" + } + + return fromPath, toPath +} + func parseChunkHeader(value string) (Chunk, error) { parts := strings.Split(value, " ") diff --git a/pkg/git/diff_test.go b/pkg/git/diff_test.go index 563e73a9e..41ea9baf7 100644 --- a/pkg/git/diff_test.go +++ b/pkg/git/diff_test.go @@ -105,6 +105,24 @@ var _ = Describe("Diff", func() { {FromPath: fromPath, ToPath: toPath}, })) }) + + fromPath = "from bar.txt" + toPath = "to foo.txt" + + It("decodes the paths correctly with whitespace in both from and to path", func() { + Expect(git.Diff(tempDir, baseSHA)).To(ConsistOf([]git.FilePatch{ + {FromPath: fromPath, ToPath: toPath}, + })) + }) + + fromPath = "from bar.txt" + toPath = "to.txt" + + It("decodes the paths correctly with whitespace in from path", func() { + Expect(git.Diff(tempDir, baseSHA)).To(ConsistOf([]git.FilePatch{ + {FromPath: fromPath, ToPath: toPath}, + })) + }) }) When("a file contains changes", func() {