Skip to content

Commit 8df1e99

Browse files
committed
repo set-default: support bare git repos
The command was using this to check for git repo context: git rev-parse --is-inside-work-tree With this change, this is used instead: git rev-parse --git-dir The latter approach works in the context of a bare git repository, which does not have a worktree.
1 parent ba27e5b commit 8df1e99

File tree

4 files changed

+42
-24
lines changed

4 files changed

+42
-24
lines changed

git/client.go

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ import (
2020

2121
var remoteRE = regexp.MustCompile(`(.+)\s+(.+)\s+\((push|fetch)\)`)
2222

23+
type errWithExitCode interface {
24+
ExitCode() int
25+
}
26+
2327
type Client struct {
2428
GhPath string
2529
RepoDir string
@@ -489,21 +493,16 @@ func (c *Client) AddRemote(ctx context.Context, name, urlStr string, trackingBra
489493
return remote, nil
490494
}
491495

492-
func (c *Client) InGitDirectory(ctx context.Context) bool {
493-
showCmd, err := c.Command(ctx, "rev-parse", "--is-inside-work-tree")
494-
if err != nil {
495-
return false
496-
}
497-
out, err := showCmd.Output()
496+
func (c *Client) IsLocalGitRepo(ctx context.Context) (bool, error) {
497+
_, err := c.GitDir(ctx)
498498
if err != nil {
499-
return false
500-
}
501-
502-
split := strings.Split(string(out), "\n")
503-
if len(split) > 0 {
504-
return split[0] == "true"
499+
var execError errWithExitCode
500+
if errors.As(err, &execError) && execError.ExitCode() == 128 {
501+
return false, nil
502+
}
503+
return false, err
505504
}
506-
return false
505+
return true, nil
507506
}
508507

509508
func (c *Client) UnsetRemoteResolution(ctx context.Context, name string) error {

internal/run/stub.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,36 @@ type commandStub struct {
106106
callbacks []CommandCallback
107107
}
108108

109+
type errWithExitCode struct {
110+
message string
111+
exitCode int
112+
}
113+
114+
func (e errWithExitCode) Error() string {
115+
return e.message
116+
}
117+
118+
func (e errWithExitCode) ExitCode() int {
119+
return e.exitCode
120+
}
121+
109122
// Run satisfies Runnable
110123
func (s *commandStub) Run() error {
111124
if s.exitStatus != 0 {
112-
return fmt.Errorf("%s exited with status %d", s.pattern, s.exitStatus)
125+
// It's nontrivial to construct a fake `exec.ExitError` instance, so we return an error type
126+
// that has the `ExitCode() int` method.
127+
return errWithExitCode{
128+
message: fmt.Sprintf("%s exited with status %d", s.pattern, s.exitStatus),
129+
exitCode: s.exitStatus,
130+
}
113131
}
114132
return nil
115133
}
116134

117135
// Output satisfies Runnable
118136
func (s *commandStub) Output() ([]byte, error) {
119-
if s.exitStatus != 0 {
120-
return []byte(nil), fmt.Errorf("%s exited with status %d", s.pattern, s.exitStatus)
137+
if err := s.Run(); err != nil {
138+
return []byte(nil), err
121139
}
122140
return []byte(s.stdout), nil
123141
}

pkg/cmd/repo/setdefault/setdefault.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ func NewCmdSetDefault(f *cmdutil.Factory, runF func(*SetDefaultOptions) error) *
9090
return cmdutil.FlagErrorf("repository required when not running interactively")
9191
}
9292

93-
c := &git.Client{}
94-
95-
if !c.InGitDirectory(ctx.Background()) {
93+
if isLocal, err := opts.GitClient.IsLocalGitRepo(cmd.Context()); err != nil {
94+
return err
95+
} else if !isLocal {
9696
return errors.New("must be run from inside a git repository")
9797
}
9898

pkg/cmd/repo/setdefault/setdefault_test.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ func TestNewCmdSetDefault(t *testing.T) {
2929
{
3030
name: "no argument",
3131
gitStubs: func(cs *run.CommandStubber) {
32-
cs.Register(`git rev-parse --is-inside-work-tree`, 0, "true")
32+
cs.Register(`git rev-parse --git-dir`, 0, ".git")
3333
},
3434
input: "",
3535
output: SetDefaultOptions{},
3636
},
3737
{
3838
name: "repo argument",
3939
gitStubs: func(cs *run.CommandStubber) {
40-
cs.Register(`git rev-parse --is-inside-work-tree`, 0, "true")
40+
cs.Register(`git rev-parse --git-dir`, 0, ".git")
4141
},
4242
input: "cli/cli",
4343
output: SetDefaultOptions{Repo: ghrepo.New("cli", "cli")},
@@ -52,23 +52,23 @@ func TestNewCmdSetDefault(t *testing.T) {
5252
{
5353
name: "view flag",
5454
gitStubs: func(cs *run.CommandStubber) {
55-
cs.Register(`git rev-parse --is-inside-work-tree`, 0, "true")
55+
cs.Register(`git rev-parse --git-dir`, 0, ".git")
5656
},
5757
input: "--view",
5858
output: SetDefaultOptions{ViewMode: true},
5959
},
6060
{
6161
name: "unset flag",
6262
gitStubs: func(cs *run.CommandStubber) {
63-
cs.Register(`git rev-parse --is-inside-work-tree`, 0, "true")
63+
cs.Register(`git rev-parse --git-dir`, 0, ".git")
6464
},
6565
input: "--unset",
6666
output: SetDefaultOptions{UnsetMode: true},
6767
},
6868
{
6969
name: "run from non-git directory",
7070
gitStubs: func(cs *run.CommandStubber) {
71-
cs.Register(`git rev-parse --is-inside-work-tree`, 1, "")
71+
cs.Register(`git rev-parse --git-dir`, 128, "")
7272
},
7373
input: "",
7474
wantErr: true,
@@ -83,6 +83,7 @@ func TestNewCmdSetDefault(t *testing.T) {
8383
io.SetStderrTTY(true)
8484
f := &cmdutil.Factory{
8585
IOStreams: io,
86+
GitClient: &git.Client{GitPath: "/fake/path/to/git"},
8687
}
8788

8889
var gotOpts *SetDefaultOptions

0 commit comments

Comments
 (0)