Skip to content

Commit

Permalink
repo set-default: support bare git repos
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mislav committed Jan 18, 2023
1 parent ba27e5b commit 8df1e99
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 24 deletions.
25 changes: 12 additions & 13 deletions git/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import (

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

type errWithExitCode interface {
ExitCode() int
}

type Client struct {
GhPath string
RepoDir string
Expand Down Expand Up @@ -489,21 +493,16 @@ func (c *Client) AddRemote(ctx context.Context, name, urlStr string, trackingBra
return remote, nil
}

func (c *Client) InGitDirectory(ctx context.Context) bool {
showCmd, err := c.Command(ctx, "rev-parse", "--is-inside-work-tree")
if err != nil {
return false
}
out, err := showCmd.Output()
func (c *Client) IsLocalGitRepo(ctx context.Context) (bool, error) {
_, err := c.GitDir(ctx)
if err != nil {
return false
}

split := strings.Split(string(out), "\n")
if len(split) > 0 {
return split[0] == "true"
var execError errWithExitCode
if errors.As(err, &execError) && execError.ExitCode() == 128 {
return false, nil
}
return false, err
}
return false
return true, nil
}

func (c *Client) UnsetRemoteResolution(ctx context.Context, name string) error {
Expand Down
24 changes: 21 additions & 3 deletions internal/run/stub.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,18 +106,36 @@ type commandStub struct {
callbacks []CommandCallback
}

type errWithExitCode struct {
message string
exitCode int
}

func (e errWithExitCode) Error() string {
return e.message
}

func (e errWithExitCode) ExitCode() int {
return e.exitCode
}

// Run satisfies Runnable
func (s *commandStub) Run() error {
if s.exitStatus != 0 {
return fmt.Errorf("%s exited with status %d", s.pattern, s.exitStatus)
// It's nontrivial to construct a fake `exec.ExitError` instance, so we return an error type
// that has the `ExitCode() int` method.
return errWithExitCode{
message: fmt.Sprintf("%s exited with status %d", s.pattern, s.exitStatus),
exitCode: s.exitStatus,
}
}
return nil
}

// Output satisfies Runnable
func (s *commandStub) Output() ([]byte, error) {
if s.exitStatus != 0 {
return []byte(nil), fmt.Errorf("%s exited with status %d", s.pattern, s.exitStatus)
if err := s.Run(); err != nil {
return []byte(nil), err
}
return []byte(s.stdout), nil
}
Expand Down
6 changes: 3 additions & 3 deletions pkg/cmd/repo/setdefault/setdefault.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ func NewCmdSetDefault(f *cmdutil.Factory, runF func(*SetDefaultOptions) error) *
return cmdutil.FlagErrorf("repository required when not running interactively")
}

c := &git.Client{}

if !c.InGitDirectory(ctx.Background()) {
if isLocal, err := opts.GitClient.IsLocalGitRepo(cmd.Context()); err != nil {
return err
} else if !isLocal {
return errors.New("must be run from inside a git repository")
}

Expand Down
11 changes: 6 additions & 5 deletions pkg/cmd/repo/setdefault/setdefault_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ func TestNewCmdSetDefault(t *testing.T) {
{
name: "no argument",
gitStubs: func(cs *run.CommandStubber) {
cs.Register(`git rev-parse --is-inside-work-tree`, 0, "true")
cs.Register(`git rev-parse --git-dir`, 0, ".git")
},
input: "",
output: SetDefaultOptions{},
},
{
name: "repo argument",
gitStubs: func(cs *run.CommandStubber) {
cs.Register(`git rev-parse --is-inside-work-tree`, 0, "true")
cs.Register(`git rev-parse --git-dir`, 0, ".git")
},
input: "cli/cli",
output: SetDefaultOptions{Repo: ghrepo.New("cli", "cli")},
Expand All @@ -52,23 +52,23 @@ func TestNewCmdSetDefault(t *testing.T) {
{
name: "view flag",
gitStubs: func(cs *run.CommandStubber) {
cs.Register(`git rev-parse --is-inside-work-tree`, 0, "true")
cs.Register(`git rev-parse --git-dir`, 0, ".git")
},
input: "--view",
output: SetDefaultOptions{ViewMode: true},
},
{
name: "unset flag",
gitStubs: func(cs *run.CommandStubber) {
cs.Register(`git rev-parse --is-inside-work-tree`, 0, "true")
cs.Register(`git rev-parse --git-dir`, 0, ".git")
},
input: "--unset",
output: SetDefaultOptions{UnsetMode: true},
},
{
name: "run from non-git directory",
gitStubs: func(cs *run.CommandStubber) {
cs.Register(`git rev-parse --is-inside-work-tree`, 1, "")
cs.Register(`git rev-parse --git-dir`, 128, "")
},
input: "",
wantErr: true,
Expand All @@ -83,6 +83,7 @@ func TestNewCmdSetDefault(t *testing.T) {
io.SetStderrTTY(true)
f := &cmdutil.Factory{
IOStreams: io,
GitClient: &git.Client{GitPath: "/fake/path/to/git"},
}

var gotOpts *SetDefaultOptions
Expand Down

0 comments on commit 8df1e99

Please sign in to comment.