Skip to content

Commit 74ff94c

Browse files
masonmcelvainBagToad
authored andcommitted
feat(browse): add blame flag
1 parent 4ea9076 commit 74ff94c

2 files changed

Lines changed: 95 additions & 0 deletions

File tree

pkg/cmd/browse/browse.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ type BrowseOptions struct {
4444
SettingsFlag bool
4545
WikiFlag bool
4646
ActionsFlag bool
47+
BlameFlag bool
4748
NoBrowserFlag bool
4849
HasRepoOverride bool
4950
}
@@ -91,6 +92,9 @@ func NewCmdBrowse(f *cmdutil.Factory, runF func(*BrowseOptions) error) *cobra.Co
9192
# Open main.go at line 312
9293
$ gh browse main.go:312
9394
95+
# Open blame view for main.go at line 312
96+
$ gh browse main.go:312 --blame
97+
9498
# Open main.go with the repository at head of bug-fix branch
9599
$ gh browse main.go --branch bug-fix
96100
@@ -141,6 +145,10 @@ func NewCmdBrowse(f *cmdutil.Factory, runF func(*BrowseOptions) error) *cobra.Co
141145
return err
142146
}
143147

148+
if opts.BlameFlag && opts.SelectorArg == "" {
149+
return cmdutil.FlagErrorf("`--blame` requires a file path argument")
150+
}
151+
144152
if (isNumber(opts.SelectorArg) || isCommit(opts.SelectorArg)) && (opts.Branch != "" || opts.Commit != "") {
145153
return cmdutil.FlagErrorf("%q is an invalid argument when using `--branch` or `--commit`", opts.SelectorArg)
146154
}
@@ -163,6 +171,7 @@ func NewCmdBrowse(f *cmdutil.Factory, runF func(*BrowseOptions) error) *cobra.Co
163171
cmd.Flags().BoolVarP(&opts.WikiFlag, "wiki", "w", false, "Open repository wiki")
164172
cmd.Flags().BoolVarP(&opts.ActionsFlag, "actions", "a", false, "Open repository actions")
165173
cmd.Flags().BoolVarP(&opts.SettingsFlag, "settings", "s", false, "Open repository settings")
174+
cmd.Flags().BoolVar(&opts.BlameFlag, "blame", false, "Open blame view for a file")
166175
cmd.Flags().BoolVarP(&opts.NoBrowserFlag, "no-browser", "n", false, "Print destination URL instead of opening the browser")
167176
cmd.Flags().StringVarP(&opts.Commit, "commit", "c", "", "Select another commit by passing in the commit SHA, default is the last commit")
168177
cmd.Flags().StringVarP(&opts.Branch, "branch", "b", "", "Select another branch by passing in the branch name")
@@ -272,9 +281,16 @@ func parseSection(baseRepo ghrepo.Interface, opts *BrowseOptions) (string, error
272281
} else {
273282
rangeFragment = fmt.Sprintf("L%d", rangeStart)
274283
}
284+
if opts.BlameFlag {
285+
return fmt.Sprintf("blame/%s/%s#%s", escapePath(ref), escapePath(filePath), rangeFragment), nil
286+
}
275287
return fmt.Sprintf("blob/%s/%s?plain=1#%s", escapePath(ref), escapePath(filePath), rangeFragment), nil
276288
}
277289

290+
if opts.BlameFlag {
291+
return fmt.Sprintf("blame/%s/%s", escapePath(ref), escapePath(filePath)), nil
292+
}
293+
278294
return strings.TrimSuffix(fmt.Sprintf("tree/%s/%s", escapePath(ref), escapePath(filePath)), "/"), nil
279295
}
280296

pkg/cmd/browse/browse_test.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,29 @@ func TestNewCmdBrowse(t *testing.T) {
207207
cli: "de07febc26e19000f8c9e821207f3bc34a3c8038 --commit=12a4",
208208
wantsErr: true,
209209
},
210+
{
211+
name: "blame flag",
212+
cli: "main.go --blame",
213+
wants: BrowseOptions{
214+
BlameFlag: true,
215+
SelectorArg: "main.go",
216+
},
217+
wantsErr: false,
218+
},
219+
{
220+
name: "blame flag without file argument",
221+
cli: "--blame",
222+
wantsErr: true,
223+
},
224+
{
225+
name: "blame flag with line number",
226+
cli: "main.go:312 --blame",
227+
wants: BrowseOptions{
228+
BlameFlag: true,
229+
SelectorArg: "main.go:312",
230+
},
231+
wantsErr: false,
232+
},
210233
}
211234
for _, tt := range tests {
212235
t.Run(tt.name, func(t *testing.T) {
@@ -239,6 +262,7 @@ func TestNewCmdBrowse(t *testing.T) {
239262
assert.Equal(t, tt.wants.SettingsFlag, opts.SettingsFlag)
240263
assert.Equal(t, tt.wants.ActionsFlag, opts.ActionsFlag)
241264
assert.Equal(t, tt.wants.Commit, opts.Commit)
265+
assert.Equal(t, tt.wants.BlameFlag, opts.BlameFlag)
242266
})
243267
}
244268
}
@@ -595,6 +619,61 @@ func Test_runBrowse(t *testing.T) {
595619
expectedURL: "https://github.com/bchadwic/test/tree/trunk/77507cd94ccafcf568f8560cfecde965fcfa63e7.txt",
596620
wantsErr: false,
597621
},
622+
{
623+
name: "file with blame flag",
624+
opts: BrowseOptions{
625+
SelectorArg: "path/to/file.txt",
626+
BlameFlag: true,
627+
},
628+
baseRepo: ghrepo.New("owner", "repo"),
629+
defaultBranch: "main",
630+
expectedURL: "https://github.com/owner/repo/blame/main/path/to/file.txt",
631+
wantsErr: false,
632+
},
633+
{
634+
name: "file with blame flag and line number",
635+
opts: BrowseOptions{
636+
SelectorArg: "path/to/file.txt:42",
637+
BlameFlag: true,
638+
},
639+
baseRepo: ghrepo.New("owner", "repo"),
640+
defaultBranch: "main",
641+
expectedURL: "https://github.com/owner/repo/blame/main/path/to/file.txt#L42",
642+
wantsErr: false,
643+
},
644+
{
645+
name: "file with blame flag and line range",
646+
opts: BrowseOptions{
647+
SelectorArg: "path/to/file.txt:10-20",
648+
BlameFlag: true,
649+
},
650+
baseRepo: ghrepo.New("owner", "repo"),
651+
defaultBranch: "main",
652+
expectedURL: "https://github.com/owner/repo/blame/main/path/to/file.txt#L10-L20",
653+
wantsErr: false,
654+
},
655+
{
656+
name: "file with blame flag and branch",
657+
opts: BrowseOptions{
658+
SelectorArg: "main.go:100",
659+
BlameFlag: true,
660+
Branch: "feature-branch",
661+
},
662+
baseRepo: ghrepo.New("owner", "repo"),
663+
expectedURL: "https://github.com/owner/repo/blame/feature-branch/main.go#L100",
664+
wantsErr: false,
665+
},
666+
{
667+
name: "file with blame flag and commit",
668+
opts: BrowseOptions{
669+
SelectorArg: "src/app.js:50",
670+
BlameFlag: true,
671+
Commit: "abc123",
672+
},
673+
baseRepo: ghrepo.New("owner", "repo"),
674+
expectedURL: "https://github.com/owner/repo/blame/abc123/src/app.js#L50",
675+
wantsErr: false,
676+
},
598677
}
599678

600679
for _, tt := range tests {

0 commit comments

Comments
 (0)