feat: lodge server, client and admin

This commit is contained in:
hh committed 2026-09-19 23:33:24 +02:00
commit 95fc50e2c2
84 files changed
+7625

No files matched your search

+103
View File
@@ -0,0 +1,103 @@
package gitrepo
import (
"crypto/sha256"
"encoding/hex"
"errors"
"os/exec"
"path"
"sort"
"strings"
)
var ErrNoIdentity = errors.New("repository has no commits and no origin to identify it by")
type Repo struct {
Root string
GitDir string
CommonDir string
Key string
Name string
}
func run(dir string, args ...string) (string, error) {
out, err := exec.Command("git", append([]string{"-C", dir}, args...)...).Output()
return strings.TrimRight(string(out), "\n"), err
}
func Open(dir string) (*Repo, error) {
root, err := run(dir, "rev-parse", "--show-toplevel")
if err != nil {
return nil, err
}
gitDir, err := run(root, "rev-parse", "--absolute-git-dir")
if err != nil {
return nil, err
}
commonDir, err := run(root, "rev-parse", "--path-format=absolute", "--git-common-dir")
if err != nil {
return nil, err
}
origin, _ := run(root, "config", "--get", "remote.origin.url")
key, err := identity(root, origin)
if err != nil {
return nil, err
}
name := path.Base(normalizeURL(origin))
if origin == "" {
name = path.Base(root)
}
return &Repo{Root: root, GitDir: gitDir, CommonDir: commonDir, Key: key, Name: name}, nil
}
func identity(root, origin string) (string, error) {
shallow, _ := run(root, "rev-parse", "--is-shallow-repository")
if shallow != "true" {
roots, err := run(root, "rev-list", "--max-parents=0", "HEAD")
if err == nil && roots != "" {
hashes := strings.Fields(roots)
sort.Strings(hashes)
return hashes[0], nil
}
}
if origin == "" {
return "", ErrNoIdentity
}
sum := sha256.Sum256([]byte(normalizeURL(origin)))
return "tmp-" + hex.EncodeToString(sum[:20]), nil
}
func normalizeURL(url string) string {
url = strings.TrimSuffix(strings.TrimSuffix(strings.ToLower(url), "/"), ".git")
if _, rest, ok := strings.Cut(url, "://"); ok {
url = rest
}
if _, rest, ok := strings.Cut(url, "@"); ok {
url = rest
}
return strings.ReplaceAll(url, ":", "/")
}
func (r *Repo) Branch() string {
branch, _ := run(r.Root, "symbolic-ref", "--short", "-q", "HEAD")
return branch
}
func (r *Repo) Head() string {
sha, _ := run(r.Root, "rev-parse", "-q", "--verify", "HEAD")
return sha
}
func (r *Repo) Tracked(paths []string) map[string]bool {
tracked := map[string]bool{}
if len(paths) == 0 {
return tracked
}
out, _ := run(r.Root, append([]string{"ls-files", "-z", "--"}, paths...)...)
for _, file := range strings.Split(out, "\x00") {
if file != "" {
tracked[file] = true
}
}
return tracked
}