Skip to content

Commit

Permalink
Merge pull request #1160 from reviewdog/fix-git
Browse files Browse the repository at this point in the history
Remove needless git command dependency by GitRelWorkdir func
  • Loading branch information
haya14busa committed Apr 20, 2022
2 parents 49470d6 + 208c9d5 commit 0562aeb
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### :sparkles: Release Note <!-- optional -->

### :rocket: Enhancements
- [#1160](https://github.com/reviewdog/reviewdog/pull/1160) Remove needless git command dependency by GitRelWorkdir func
- ...

### :bug: Fixes
Expand Down
4 changes: 2 additions & 2 deletions project/run_test.go
Expand Up @@ -152,7 +152,7 @@ func TestRun(t *testing.T) {
conf := &Config{
Runner: map[string]*Runner{
"test": {
Cmd: "not found",
Cmd: "not-found",
Errorformat: []string{`%f:%l:%c:%m`},
},
},
Expand All @@ -162,7 +162,7 @@ func TestRun(t *testing.T) {
} else {
t.Log(err)
}
want := "sh: 1: not: not found\n"
want := "sh: 1: not-found: not found\n"
if got := buf.String(); got != want {
t.Errorf("got stderr %q, want %q", got, want)
}
Expand Down
88 changes: 84 additions & 4 deletions service/serviceutil/serviceutil.go
Expand Up @@ -2,15 +2,95 @@ package serviceutil

import (
"fmt"
"os/exec"
"os"
"path/filepath"
"strings"
)

// GitRelWorkdir returns git relative workdir of current directory.
//
// It should return the same output as `git rev-parse --show-prefix`.
// It does not execute `git` command to avoid needless git binary dependency.
//
// An example problem due to `git` command dependency: https://github.com/reviewdog/reviewdog/issues/1158
func GitRelWorkdir() (string, error) {
b, err := exec.Command("git", "rev-parse", "--show-prefix").Output()
cwd, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("failed to run 'git rev-parse --show-prefix': %w", err)
return "", err
}
return strings.Trim(string(b), "\n"), nil
root, err := findGitRoot(cwd)
if err != nil {
return "", err
}
if !strings.HasPrefix(cwd, root) {
return "", fmt.Errorf("cannot get GitRelWorkdir: cwd=%q, root=%q", cwd, root)
}
const separator = string(filepath.Separator)
path := strings.Trim(strings.TrimPrefix(cwd, root), separator)
if path != "" {
path += separator
}
return path, nil
}

func findGitRoot(path string) (string, error) {
gitPath, err := findDotGitPath(path)
if err != nil {
return "", err
}
return filepath.Dir(gitPath), nil
}

func findDotGitPath(path string) (string, error) {
// normalize the path
path, err := filepath.Abs(path)
if err != nil {
return "", err
}

for {
fi, err := os.Stat(filepath.Join(path, ".git"))
if err == nil {
if !fi.IsDir() {
return "", fmt.Errorf(".git exist but is not a directory")
}
return filepath.Join(path, ".git"), nil
}
if !os.IsNotExist(err) {
// unknown error
return "", err
}

// detect bare repo
ok, err := isGitDir(path)
if err != nil {
return "", err
}
if ok {
return path, nil
}

parent := filepath.Dir(path)
if parent == path {
return "", fmt.Errorf(".git not found")
}
path = parent
}
}

// ref: https://github.com/git/git/blob/3bab5d56259722843359702bc27111475437ad2a/setup.c#L328-L338
func isGitDir(path string) (bool, error) {
markers := []string{"HEAD", "objects", "refs"}
for _, marker := range markers {
_, err := os.Stat(filepath.Join(path, marker))
if err == nil {
continue
}
if !os.IsNotExist(err) {
// unknown error
return false, err
}
return false, nil
}
return true, nil
}

0 comments on commit 0562aeb

Please sign in to comment.