parent:
cba0e159e0fcd8f08f13af5673509418e8fe9e67
nmyk <nick@nmyk.io>
2026-04-21T19:17:51-04:00
fixes git clone bug info/refs and upload-pack did not work with --directory specified
diff --git a/internal/core/repo.go b/internal/core/repo.go
index 5a947efa56094282502ac9e815ebe5b4724d9c0f..6607f5443a42ab968757502d3203fe0f9d49492b 100644
--- a/internal/core/repo.go
+++ b/internal/core/repo.go
@@ -5,7 +5,6 @@ "bytes"
"errors"
"fmt"
"io"
- "os"
"path"
"strings"
@@ -17,49 +16,9 @@ "github.com/go-git/go-git/v6/plumbing/object"
"github.com/go-git/go-git/v6/utils/binary"
)
-const dotGit = ".git"
-
-func List(dir string) ([]*Repo, error) {
- entries, err := os.ReadDir(dir)
- if err != nil {
- return nil, err
- }
- var repos []*Repo
- for _, e := range entries {
- if e.Name() == dotGit {
- continue
- }
- repo, err := Open(strings.TrimSuffix(e.Name(), dotGit))
- if err == nil {
- if _, err = repo.Worktree(); errors.Is(err, git.ErrIsBareRepository) {
- repos = append(repos, repo)
- }
- }
- }
- if len(repos) == 0 {
- return nil, errors.New("No repos found in " + dir)
- }
- return repos, nil
-}
-
type Repo struct {
*git.Repository
Name string
-}
-
-func Open(repoName string) (*Repo, error) {
- if _, err := os.Stat(repoName + dotGit); os.IsNotExist(err) {
- return nil, err
- }
- repo, err := git.PlainOpen(repoName + dotGit)
- if err != nil {
- return nil, err
- }
- return &Repo{repo, repoName}, nil
-}
-
-func (repo *Repo) Path() string {
- return repo.Name + dotGit
}
func (repo *Repo) Load(entry *object.TreeEntry) (string, error) {
diff --git a/internal/handlers/directory.go b/internal/handlers/directory.go
new file mode 100644
index 0000000000000000000000000000000000000000..6043457d4d2bdd4bf1971b67e21ea5ac65e93637
--- /dev/null
+++ b/internal/handlers/directory.go
@@ -0,0 +1,51 @@
+package handlers
+
+import (
+ "errors"
+ "os"
+ "path"
+ "strings"
+
+ "github.com/go-git/go-git/v6"
+ "nmyk.io/bidet/internal/core"
+)
+
+const dotGit = ".git"
+
+func (s Server) List() ([]*core.Repo, error) {
+ entries, err := os.ReadDir(s.Dir)
+ if err != nil {
+ return nil, err
+ }
+ var repos []*core.Repo
+ for _, e := range entries {
+ if e.Name() == dotGit {
+ continue
+ }
+ repo, err := s.Open(strings.TrimSuffix(e.Name(), dotGit))
+ if err == nil {
+ if _, err = repo.Worktree(); errors.Is(err, git.ErrIsBareRepository) {
+ repos = append(repos, repo)
+ }
+ }
+ }
+ if len(repos) == 0 {
+ return nil, errors.New("No repos found in " + s.Dir)
+ }
+ return repos, nil
+}
+
+func (s Server) repoPath(repoName string) string {
+ return path.Join(s.Dir, repoName) + dotGit
+}
+
+func (s Server) Open(repoName string) (*core.Repo, error) {
+ if _, err := os.Stat(s.repoPath(repoName)); os.IsNotExist(err) {
+ return nil, err
+ }
+ repo, err := git.PlainOpen(s.repoPath(repoName))
+ if err != nil {
+ return nil, err
+ }
+ return &core.Repo{Repository: repo, Name: repoName}, nil
+}
diff --git a/internal/handlers/handlers.go b/internal/handlers/handlers.go
index 5b6180c9f368e86454f109a4aa8d81e90228ad97..85ba4192e852a173598c5bdf8165902149dcc049 100644
--- a/internal/handlers/handlers.go
+++ b/internal/handlers/handlers.go
@@ -131,7 +131,7 @@ Updated time.Time
}
func (s Server) ListRepos(w http.ResponseWriter, _ *http.Request) {
- repos, err := core.List(s.Dir)
+ repos, err := s.List()
if err != nil {
s.error(w, err)
return
@@ -184,13 +184,9 @@ Branches []BranchMeta
Tags []TagMeta
}
-func (s Server) open(name string) (*core.Repo, error) {
- return core.Open(path.Join(s.Dir, name))
-}
-
func (s Server) Refs(w http.ResponseWriter, r *http.Request) {
repoName := r.PathValue("name")
- repo, err := s.open(repoName)
+ repo, err := s.Open(repoName)
if err != nil {
s.error(w, err)
return
@@ -300,7 +296,7 @@ }
func (s Server) Commits(w http.ResponseWriter, r *http.Request) {
repoName := r.PathValue("name")
- repo, err := s.open(repoName)
+ repo, err := s.Open(repoName)
if err != nil {
s.error(w, err)
return
@@ -343,7 +339,7 @@ ctx, cancel := context.WithCancel(r.Context())
defer cancel()
cmd := exec.CommandContext(ctx, "git", args...)
- cmd.Dir = path.Join(s.Dir, repo.Path())
+ cmd.Dir = s.repoPath(repoName)
stdout, err := cmd.StdoutPipe()
if err != nil {
s.error(w, err)
@@ -454,7 +450,7 @@ }
func (s Server) Commit(w http.ResponseWriter, r *http.Request) {
repoName := r.PathValue("name")
- repo, err := s.open(repoName)
+ repo, err := s.Open(repoName)
if err != nil {
s.error(w, err)
return
@@ -511,7 +507,7 @@ }
func (s Server) Blob(w http.ResponseWriter, r *http.Request) {
repoName := r.PathValue("name")
- repo, err := s.open(repoName)
+ repo, err := s.Open(repoName)
if err != nil {
s.error(w, err)
return
@@ -568,7 +564,7 @@ }
func (s Server) Tree(w http.ResponseWriter, r *http.Request) {
repoName := r.PathValue("name")
- repo, err := s.open(repoName)
+ repo, err := s.Open(repoName)
if err != nil {
s.error(w, err)
return
@@ -679,8 +675,14 @@ }
}
func (s Server) InfoRefs(w http.ResponseWriter, r *http.Request) {
- repoName := r.PathValue("name")
- repo, err := git.PlainOpen(repoName)
+ repoDir := r.PathValue("name")
+ // repoDir already ends in .git
+ repoLocation, cut := strings.CutSuffix(s.repoPath(repoDir), dotGit)
+ if !cut {
+ http.NotFound(w, r)
+ return
+ }
+ repo, err := git.PlainOpen(repoLocation)
if err != nil {
s.error(w, err)
return
@@ -697,7 +699,13 @@ }
}
func (s Server) UploadPack(w http.ResponseWriter, r *http.Request) {
- repoName := r.PathValue("name")
+ repoDir := r.PathValue("name")
+ // repoDir already ends in .git
+ repoLocation, cut := strings.CutSuffix(s.repoPath(repoDir), dotGit)
+ if !cut {
+ http.NotFound(w, r)
+ return
+ }
var bodyReader io.ReadCloser
switch strings.ToLower(r.Header.Get("Content-Encoding")) {
case "gzip":
@@ -714,7 +722,7 @@ }
w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-result", r.PathValue("path")))
w.Header().Add("Cache-Control", "no-cache")
w.WriteHeader(http.StatusOK)
- if err := core.UploadPack(repoName, bodyReader, w); err != nil {
+ if err := core.UploadPack(repoLocation, bodyReader, w); err != nil {
s.error(w, err)
return
}
@@ -722,7 +730,7 @@ }
func (s Server) RepoTree(w http.ResponseWriter, r *http.Request) {
repoName := r.PathValue("name")
- repo, err := s.open(repoName)
+ repo, err := s.Open(repoName)
if err != nil {
s.error(w, err)
return