all repos — elgit @ fed19ae329323cca0f7b49624486966fbce8096b

fork of legit: web frontend for git, written in go

use gitweb/gitolite directory layout (including subdirs)

Alan Pearce
commit

fed19ae329323cca0f7b49624486966fbce8096b

parent

9c336ff148d48d09a4f4866798511cdcce50202a

1 file changed, 60 insertions(+), 53 deletions(-)

changed files
M routes/util.goroutes/util.go
@@ -1,13 +1,18 @@
package routes import ( - "io/fs" + "bytes" "log" "net/http" "os" "path/filepath" + "slices" "strings" + securejoin "github.com/cyphar/filepath-securejoin" + "github.com/dimfeld/httptreemux/v5" + "go.alanpearce.eu/elgit/config" + "go.alanpearce.eu/elgit/data" "go.alanpearce.eu/elgit/git" )
@@ -40,71 +45,73 @@
return false } -func (d *deps) isIgnored(name string) bool { - for _, i := range d.c.Repo.Ignore { - if name == i { - return true - } +func (d *deps) isNotAllowed(name string) bool { + return !slices.Contains(d.projects, name) +} + +func (d *deps) GetCleanPath(name string) (string, error) { + return securejoin.SecureJoin( + filepath.Join(d.c.Repo.Root, "repositories"), + httptreemux.Clean(name)+".git", + ) +} + +func ReadProjectsList(c *config.Config) ([]string, error) { + content, err := os.ReadFile(filepath.Join(c.Repo.Root, "projects.list")) + if err != nil { + return nil, err } + lines := bytes.SplitSeq(content, []byte("\n")) - return false -} + projects := []string{} + for line := range lines { + projects = append(projects, strings.TrimSuffix(string(line), ".git")) + } -type repoInfo struct { - Git *git.GitRepo - Path string - Category string + return projects, nil } -func (d *deps) getAllRepos() ([]repoInfo, error) { - repos := []repoInfo{} - max := strings.Count(d.c.Repo.ScanPath, string(os.PathSeparator)) + 2 +func (d *deps) getAllRepos() *data.Entries { + entries := &data.Entries{ + Children: []*data.Entry{}, + Map: map[string]*data.Entry{}, + } - err := filepath.WalkDir(d.c.Repo.ScanPath, func(path string, de fs.DirEntry, err error) error { - if err != nil { - return err + for _, project := range d.projects { + if project == "" || d.isUnlisted(project) { + continue } + fullPath := filepath.Join(d.c.Repo.Root, "repositories", project+".git") - if de.IsDir() { - // Check if we've exceeded our recursion depth - if strings.Count(path, string(os.PathSeparator)) > max { - return fs.SkipDir - } - - if d.isIgnored(path) { - return fs.SkipDir - } - - // A bare repo should always have at least a HEAD file, if it - // doesn't we can continue recursing - if _, err := os.Lstat(filepath.Join(path, "HEAD")); err == nil { - repo, err := git.Open(path, "") - if err != nil { - log.Println(err) - } else { - relpath, _ := filepath.Rel(d.c.Repo.ScanPath, path) - repos = append(repos, repoInfo{ - Git: repo, - Path: relpath, - Category: d.category(path), - }) - // Since we found a Git repo, we don't want to recurse - // further - return fs.SkipDir + // A bare repo should always have at least a HEAD file + if _, err := os.Lstat(filepath.Join(fullPath, "HEAD")); err == nil { + repo, err := git.Open(fullPath, "") + if err != nil { + log.Println(err) + } else { + category, name, found := strings.Cut(project, string(os.PathSeparator)) + if !found { + category = "" + name = project } + r := data.Repository{ + Name: name, + Category: category, + Path: fullPath, + Slug: project, + Description: getDescription(fullPath), + } + if cc, err := repo.LastCommit(); err == nil { + r.LastCommit = cc.Author.When + } + entries.Add(r) } } - return nil - }) + } - return repos, err -} + entries.Sort() -func (d *deps) category(path string) string { - return strings.TrimPrefix( - filepath.Dir(strings.TrimPrefix(path, d.c.Repo.ScanPath)), - string(os.PathSeparator), - ) + return entries } func setContentDisposition(w http.ResponseWriter, name string) {