summaryrefslogtreecommitdiff
path: root/pkg/git
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/git')
-rw-r--r--pkg/git/git.go16
-rw-r--r--pkg/git/types.go24
-rw-r--r--pkg/git/utils.go15
-rw-r--r--pkg/git/utils_test.go24
4 files changed, 70 insertions, 9 deletions
diff --git a/pkg/git/git.go b/pkg/git/git.go
index 9139261..7fc28fa 100644
--- a/pkg/git/git.go
+++ b/pkg/git/git.go
@@ -31,7 +31,7 @@ func Branches(repoDir string, filter *regexp.Regexp, defaultBranch string) ([]Re
if filter != nil && !filter.MatchString(line) && line != defaultBranch {
continue
}
- branches = append(branches, Ref(line))
+ branches = append(branches, NewRef(line))
}
return branches, nil
}
@@ -88,13 +88,13 @@ func Tags(repoDir string) ([]Tag, error) {
}
func Files(ref Ref, repoDir string) ([]Blob, error) {
- if ref == "" {
- ref = "HEAD"
+ if ref.IsEmpty() {
+ ref = NewRef("HEAD")
}
// -r: recurse into subtrees
// -l: include blob size
- cmd := exec.Command("git", "ls-tree", "--full-tree", "-r", "-l", string(ref))
+ cmd := exec.Command("git", "ls-tree", "--full-tree", "-r", "-l", ref.Ref())
if repoDir != "" {
cmd.Dir = repoDir
}
@@ -196,11 +196,11 @@ func Files(ref Ref, repoDir string) ([]Blob, error) {
}
func BlobContent(ref Ref, path string, repoDir string) ([]byte, bool, error) {
- if ref == "" {
- ref = "HEAD"
+ if ref.IsEmpty() {
+ ref = NewRef("HEAD")
}
// Use `git show ref:path` to get the blob content at that ref
- cmd := exec.Command("git", "show", string(ref)+":"+path)
+ cmd := exec.Command("git", "show", ref.Ref()+":"+path)
if repoDir != "" {
cmd.Dir = repoDir
}
@@ -233,7 +233,7 @@ func Commits(ref Ref, repoDir string) ([]Commit, error) {
"--date=unix",
"--pretty=format:" + strings.Join(format, "\x1F"),
"-z", // Separate the commits with NULs instead of newlines
- string(ref),
+ ref.Ref(),
}
cmd := exec.Command("git", args...)
diff --git a/pkg/git/types.go b/pkg/git/types.go
index 3c12f14..121c7d8 100644
--- a/pkg/git/types.go
+++ b/pkg/git/types.go
@@ -4,7 +4,29 @@ import (
"time"
)
-type Ref string
+type Ref struct {
+ ref string
+ dirName string
+}
+
+func NewRef(ref string) Ref {
+ return Ref{
+ ref: ref,
+ dirName: RefToFileName(ref),
+ }
+}
+
+func (r Ref) IsEmpty() bool {
+ return r.ref == ""
+}
+
+func (r Ref) Ref() string {
+ return r.ref
+}
+
+func (r Ref) DirName() string {
+ return r.dirName
+}
type Blob struct {
Ref Ref
diff --git a/pkg/git/utils.go b/pkg/git/utils.go
index 24a2b75..68e4497 100644
--- a/pkg/git/utils.go
+++ b/pkg/git/utils.go
@@ -3,6 +3,7 @@ package git
import (
"fmt"
"strconv"
+ "strings"
)
// ParseFileMode converts a git-style file mode (e.g. "100644")
@@ -74,3 +75,17 @@ func IsBinary(b []byte) bool {
// If more than 30% of sampled bytes are non-text, consider binary
return bad*100 > n*30
}
+
+func RefToFileName(ref string) string {
+ var result strings.Builder
+ for _, c := range ref {
+ if (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '.' {
+ result.WriteByte(byte(c))
+ } else if c >= 'A' && c <= 'Z' {
+ result.WriteByte(byte(c - 'A' + 'a'))
+ } else {
+ result.WriteByte('-')
+ }
+ }
+ return result.String()
+}
diff --git a/pkg/git/utils_test.go b/pkg/git/utils_test.go
index ecbe952..4dcebe8 100644
--- a/pkg/git/utils_test.go
+++ b/pkg/git/utils_test.go
@@ -54,3 +54,27 @@ func TestParseFileModeInvalid(t *testing.T) {
})
}
}
+
+func TestRefToFileName(t *testing.T) {
+ tests := []struct {
+ in string
+ want string
+ }{
+ {"main", "main"},
+ {"master", "master"},
+ {"release/v1.0", "release-v1.0"},
+ {"feature/add-login", "feature-add-login"},
+ {"bugfix\\windows\\path", "bugfix-windows-path"},
+ {"1.0.0", "1.0.0"},
+ {"1.x", "1.x"},
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.in, func(t *testing.T) {
+ got := git.RefToFileName(tt.in)
+ if got != tt.want {
+ t.Fatalf("refToFileName(%q) = %q, want %q", tt.in, got, tt.want)
+ }
+ })
+ }
+}