diff --git a/pkg/cmd/pr/diff/diff.go b/pkg/cmd/pr/diff/diff.go index 95fce5cd1..b7ef11707 100644 --- a/pkg/cmd/pr/diff/diff.go +++ b/pkg/cmd/pr/diff/diff.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net/http" + "regexp" "strings" "github.com/MakeNowJust/heredoc" @@ -27,6 +28,7 @@ type DiffOptions struct { SelectorArg string UseColor bool Patch bool + NameOnly bool } func NewCmdDiff(f *cmdutil.Factory, runF func(*DiffOptions) error) *cobra.Command { @@ -78,6 +80,7 @@ func NewCmdDiff(f *cmdutil.Factory, runF func(*DiffOptions) error) *cobra.Comman cmdutil.StringEnumFlag(cmd, &colorFlag, "color", "", "auto", []string{"always", "never", "auto"}, "Use color in diff output") cmd.Flags().BoolVar(&opts.Patch, "patch", false, "Display diff in patch format") + cmd.Flags().BoolVar(&opts.NameOnly, "name-only", false, "Display only names of changed files") return cmd } @@ -97,6 +100,10 @@ func diffRun(opts *DiffOptions) error { return err } + if opts.NameOnly { + opts.Patch = false + } + diff, err := fetchDiff(httpClient, baseRepo, pr.Number, opts.Patch) if err != nil { return fmt.Errorf("could not find pull request diff: %w", err) @@ -109,6 +116,10 @@ func diffRun(opts *DiffOptions) error { fmt.Fprintf(opts.IO.ErrOut, "failed to start pager: %v\n", err) } + if opts.NameOnly { + return changedFilesNames(opts.IO.Out, diff) + } + if !opts.UseColor { _, err = io.Copy(opts.IO.Out, diff) return err @@ -227,3 +238,22 @@ func isAdditionLine(l []byte) bool { func isRemovalLine(l []byte) bool { return len(l) > 0 && l[0] == '-' } + +func changedFilesNames(w io.Writer, r io.Reader) error { + diff, err := io.ReadAll(r) + if err != nil { + return err + } + + pattern := regexp.MustCompile(`(?:^|\n)diff\s--git.*\sb/(.*)`) + matches := pattern.FindAllStringSubmatch(string(diff), -1) + + for _, val := range matches { + name := strings.TrimSpace(val[1]) + if _, err := w.Write([]byte(name + "\n")); err != nil { + return err + } + } + + return nil +} diff --git a/pkg/cmd/pr/diff/diff_test.go b/pkg/cmd/pr/diff/diff_test.go index a734ac439..e8d694676 100644 --- a/pkg/cmd/pr/diff/diff_test.go +++ b/pkg/cmd/pr/diff/diff_test.go @@ -170,6 +170,18 @@ func Test_diffRun(t *testing.T) { wantAccept: "application/vnd.github.v3.patch", wantStdout: fmt.Sprintf(testDiff, "", "", "", ""), }, + { + name: "name only", + opts: DiffOptions{ + SelectorArg: "123", + UseColor: false, + Patch: false, + NameOnly: true, + }, + rawDiff: fmt.Sprintf(testDiff, "", "", "", ""), + wantAccept: "application/vnd.github.v3.diff", + wantStdout: fmt.Sprintf(".github/workflows/releases.yml\nMakefile\n"), + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -290,3 +302,43 @@ func Test_colorDiffLines(t *testing.T) { } } } + +func Test_changedFileNames(t *testing.T) { + inputs := []struct { + input, output string + }{ + { + input: "", + output: "", + }, + { + input: "\n", + output: "", + }, + { + input: "diff --git a/cmd.go b/cmd.go\n--- /dev/null\n+++ b/cmd.go\n@@ -0,0 +1,313 @@", + output: "cmd.go\n", + }, + { + input: "diff --git a/cmd.go b/cmd.go\n--- a/cmd.go\n+++ /dev/null\n@@ -0,0 +1,313 @@", + output: "cmd.go\n", + }, + { + input: fmt.Sprintf("diff --git a/baz.go b/rename.go\n--- a/baz.go\n+++ b/rename.go\n+foo\n-b%sr", strings.Repeat("a", 2*lineBufferSize)), + output: "rename.go\n", + }, + { + input: fmt.Sprintf("diff --git a/baz.go b/baz.go\n--- a/baz.go\n+++ b/baz.go\n+foo\n-b%sr", strings.Repeat("a", 2*lineBufferSize)), + output: "baz.go\n", + }, + } + for _, tt := range inputs { + buf := bytes.Buffer{} + if err := changedFilesNames(&buf, strings.NewReader(tt.input)); err != nil { + t.Fatalf("unexpected error: %s", err) + } + if got := buf.String(); got != tt.output { + t.Errorf("expected: %q, got: %q", tt.output, got) + } + } +}