all repos — legit @ d6fa0d66c9f6a6c41030f28872132f4290671c48

Unnamed repository; edit this file 'description' to name the repository.

routes/util.go (view raw)

  1package routes
  2
  3import (
  4	"io/fs"
  5	"log"
  6	"net/http"
  7	"os"
  8	"path/filepath"
  9	"strings"
 10
 11	"git.icyphox.sh/legit/git"
 12)
 13
 14func isGoModule(gr *git.GitRepo) bool {
 15	_, err := gr.FileContent("go.mod")
 16	return err == nil
 17}
 18
 19func getDisplayName(name string) string {
 20	return strings.TrimSuffix(name, ".git")
 21}
 22
 23func getDescription(path string) (desc string) {
 24	db, err := os.ReadFile(filepath.Join(path, "description"))
 25	if err == nil {
 26		desc = string(db)
 27	} else {
 28		desc = ""
 29	}
 30	return
 31}
 32
 33func (d *deps) isUnlisted(name string) bool {
 34	for _, i := range d.c.Repo.Unlisted {
 35		if name == i {
 36			return true
 37		}
 38	}
 39
 40	return false
 41}
 42
 43func (d *deps) isIgnored(name string) bool {
 44	for _, i := range d.c.Repo.Ignore {
 45		if name == i {
 46			return true
 47		}
 48	}
 49
 50	return false
 51}
 52
 53type repoInfo struct {
 54	Git      *git.GitRepo
 55	Path     string
 56	Category string
 57}
 58
 59func (d *deps) getAllRepos() ([]repoInfo, error) {
 60	repos := []repoInfo{}
 61	seen := map[string]bool{}
 62	max := strings.Count(d.c.Repo.ScanPath, string(os.PathSeparator)) + 2
 63
 64	err := filepath.WalkDir(d.c.Repo.ScanPath, func(path string, de fs.DirEntry, err error) error {
 65		if err != nil {
 66			return err
 67		}
 68
 69		if de.IsDir() {
 70			// Check if we've exceeded our recursion depth
 71			if strings.Count(path, string(os.PathSeparator)) > max {
 72				return fs.SkipDir
 73			}
 74
 75			if d.isIgnored(path) {
 76				return fs.SkipDir
 77			}
 78
 79			// A bare repo should always have at least a HEAD file, if it
 80			// doesn't we can continue recursing
 81			if _, err := os.Lstat(filepath.Join(path, "HEAD")); err == nil {
 82				repo, err := git.Open(path, "")
 83				if err != nil {
 84					log.Println(err)
 85				} else {
 86					relpath, _ := filepath.Rel(d.c.Repo.ScanPath, path)
 87					repos = append(repos, repoInfo{
 88						Git:      repo,
 89						Path:     relpath,
 90						Category: d.category(path),
 91					})
 92					// Since we found a Git repo, we don't want to recurse
 93					// further
 94					return fs.SkipDir
 95				}
 96			}
 97		} else if de.Type()&fs.ModeSymlink != 0 {
 98			if d.isIgnored(path) {
 99				return nil
100			}
101
102			target, err := filepath.EvalSymlinks(path)
103			if err != nil {
104				log.Printf("failed to resolve symlink %s: %v", path, err)
105				return nil
106			}
107
108			// Avoid duplicates if multiple symlinks point to the same target
109			if seen[target] {
110				return nil
111			}
112			seen[target] = true
113
114			if _, err := os.Stat(filepath.Join(target, "HEAD")); err == nil {
115				repo, err := git.Open(target, "")
116				if err != nil {
117					log.Println(err)
118				} else {
119					relpath, _ := filepath.Rel(d.c.Repo.ScanPath, path)
120					repos = append(repos, repoInfo{
121						Git:      repo,
122						Path:     relpath,
123						Category: d.category(path),
124					})
125				}
126			}
127		}
128		return nil
129	})
130
131	return repos, err
132}
133
134func (d *deps) category(path string) string {
135	return strings.TrimPrefix(filepath.Dir(strings.TrimPrefix(path, d.c.Repo.ScanPath)), string(os.PathSeparator))
136}
137
138func setContentDisposition(w http.ResponseWriter, name string) {
139	h := "inline; filename=\"" + name + "\""
140	w.Header().Add("Content-Disposition", h)
141}
142
143func setGZipMIME(w http.ResponseWriter) {
144	setMIME(w, "application/gzip")
145}
146
147func setMIME(w http.ResponseWriter, mime string) {
148	w.Header().Add("Content-Type", mime)
149}