From 866b215aba54bbd5fcc65a451b263b5061720bcd Mon Sep 17 00:00:00 2001 From: Axenos-dev Date: Sun, 5 Jul 2026 10:09:56 -0700 Subject: [PATCH 1/7] Repository contents endpoint --- internal/domain/contents.go | 40 ++++ internal/gitbackend/backend.go | 1 + internal/gitbackend/local.go | 124 ++++++++++ internal/gitbackend/local_test.go | 220 ++++++++++++++++++ internal/gitbackend/types.go | 26 +++ .../server/control/repositories/contents.go | 43 ++++ .../server/control/repositories/handlers.go | 2 + internal/server/control/repositories/types.go | 46 ++++ internal/server/response/codes.go | 2 + internal/services/repositories/errors.go | 5 + internal/services/repositories/service.go | 53 +++++ 11 files changed, 562 insertions(+) create mode 100644 internal/domain/contents.go create mode 100644 internal/server/control/repositories/contents.go diff --git a/internal/domain/contents.go b/internal/domain/contents.go new file mode 100644 index 0000000..cf37056 --- /dev/null +++ b/internal/domain/contents.go @@ -0,0 +1,40 @@ +package domain + +type TreeEntryType string + +const ( + TreeEntryFile TreeEntryType = "file" + TreeEntryDir TreeEntryType = "dir" + TreeEntrySymlink TreeEntryType = "symlink" + TreeEntrySubmodule TreeEntryType = "submodule" +) + +func TreeEntryTypeFromMode(mode string) TreeEntryType { + switch mode { + case "040000": + return TreeEntryDir + case "120000": + return TreeEntrySymlink + case "160000": + return TreeEntrySubmodule + default: // 100644, 100755 + return TreeEntryFile + } +} + +type TreeEntry struct { + Name string + Path string // full path from the repo root + Type TreeEntryType + Mode string + SHA string + Size int64 // object size in bytes, -1 for non-blobs (dirs, submodules) +} + +type RepositoryContents struct { + Ref string + CommitSHA string + Path string + Entries []TreeEntry + Truncated bool +} diff --git a/internal/gitbackend/backend.go b/internal/gitbackend/backend.go index e7b6e7e..9815790 100644 --- a/internal/gitbackend/backend.go +++ b/internal/gitbackend/backend.go @@ -12,4 +12,5 @@ type Backend interface { AdvertiseRefs(ctx context.Context, storagePath string, svc Service, stdout io.Writer) error UploadPack(ctx context.Context, storagePath string, stateless bool, stdin io.Reader, stdout, stderr io.Writer) error ReceivePack(ctx context.Context, storagePath string, stateless bool, stdin io.Reader, stdout, stderr io.Writer) ([]RefChange, error) + ListTree(ctx context.Context, storagePath, rev, treePath string) (TreeListing, error) } diff --git a/internal/gitbackend/local.go b/internal/gitbackend/local.go index d46dbb8..94ac2ff 100644 --- a/internal/gitbackend/local.go +++ b/internal/gitbackend/local.go @@ -8,7 +8,9 @@ import ( "io" "os" "os/exec" + "path" "path/filepath" + "strconv" "strings" "sync" "time" @@ -198,6 +200,128 @@ func (l *Local) listRefs(ctx context.Context, storagePath string) (map[string]st return refs, sc.Err() } +func (l *Local) ListTree(ctx context.Context, storagePath, rev, treePath string) (TreeListing, error) { + dir, err := l.resolve(storagePath) + if err != nil { + return TreeListing{}, err + } + + rev, err = normalizeRev(rev) + if err != nil { + return TreeListing{}, err + } + treePath, err = normalizeTreePath(treePath) + if err != nil { + return TreeListing{}, err + } + + ctx, cancel := context.WithTimeout(ctx, l.timeout) + defer cancel() + + commitSHA, err := l.revParse(ctx, dir, rev+"^{commit}") + if err != nil { + return TreeListing{}, fmt.Errorf("%w: %s", ErrRevNotFound, rev) + } + + treeish := commitSHA + if treePath != "" { + treeish += ":" + treePath + } + + cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "ls-tree", "--long", "-z", "--end-of-options", treeish) + var out, stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + // the rev already resolved, so this is a missing path or a non-directory + return TreeListing{}, fmt.Errorf("%w: %q", ErrPathNotFound, treePath) + } + + entries, truncated, err := parseLsTree(out.Bytes(), treePath) + if err != nil { + return TreeListing{}, err + } + return TreeListing{CommitSHA: commitSHA, Entries: entries, Truncated: truncated}, nil +} + +// revParse resolves a rev expression to an object id, failing when the object does not exist +func (l *Local) revParse(ctx context.Context, dir, spec string) (string, error) { + cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "rev-parse", "--verify", "--end-of-options", spec) + var out, stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("rev-parse: %w: %s", err, strings.TrimSpace(stderr.String())) + } + return strings.TrimSpace(out.String()), nil +} + +func parseLsTree(out []byte, treePath string) ([]TreeEntry, bool, error) { + var entries []TreeEntry + // each record has a shape like " \t" + for record := range bytes.SplitSeq(out, []byte{0}) { + if len(record) == 0 { + continue + } + if len(entries) == maxTreeEntries { + return entries, true, nil + } + + // header never contains a tab, but a filename can, so cut at the first one + header, name, ok := bytes.Cut(record, []byte{'\t'}) + if !ok { + return nil, false, fmt.Errorf("malformed ls-tree record: %q", record) + } + fields := strings.Fields(string(header)) + if len(fields) != 4 { + return nil, false, fmt.Errorf("malformed ls-tree header: %q", header) + } + + size := int64(-1) + // if size is "-" -> its non-blob item -> size = -1 + if fields[3] != "-" { + parsed, err := strconv.ParseInt(fields[3], 10, 64) + if err != nil { + return nil, false, fmt.Errorf("malformed ls-tree size %q: %w", fields[3], err) + } + size = parsed + } + + entries = append(entries, TreeEntry{ + Mode: fields[0], + Type: fields[1], + SHA: fields[2], + Size: size, + Path: path.Join(treePath, string(name)), + }) + } + return entries, false, nil +} + +// normalizeRev validates an untrusted revision expression; empty means HEAD +func normalizeRev(rev string) (string, error) { + if rev == "" { + return "HEAD", nil + } + if strings.HasPrefix(rev, "-") { + return "", fmt.Errorf("%w: %q", ErrInvalidRev, rev) + } + for _, r := range rev { + if r < 0x20 || r == 0x7f { + return "", fmt.Errorf("%w: control character", ErrInvalidRev) + } + } + return rev, nil +} + +// normalizeTreePath validates an untrusted tree path and normalizes it +func normalizeTreePath(p string) (string, error) { + if strings.ContainsRune(p, 0) { + return "", fmt.Errorf("%w: contains NUL", ErrInvalidPath) + } + return path.Clean("/" + p)[1:], nil +} + func (l *Local) lockRepo(storagePath string) func() { l.mu.Lock() m, ok := l.locks[storagePath] diff --git a/internal/gitbackend/local_test.go b/internal/gitbackend/local_test.go index 2461b76..4d512c5 100644 --- a/internal/gitbackend/local_test.go +++ b/internal/gitbackend/local_test.go @@ -1,6 +1,11 @@ package gitbackend import ( + "context" + "errors" + "fmt" + "os" + "os/exec" "path/filepath" "sort" "strings" @@ -40,6 +45,221 @@ func TestResolveContainment(t *testing.T) { } } +func TestNormalizeRev(t *testing.T) { + cases := []struct { + name, rev, want string + wantErr error + }{ + {"empty defaults to HEAD", "", "HEAD", nil}, + {"branch", "main", "main", nil}, + {"expression", "main~2", "main~2", nil}, + {"option injection", "--help", "", ErrInvalidRev}, + {"leading dash", "-x", "", ErrInvalidRev}, + {"newline", "main\nx", "", ErrInvalidRev}, + {"nul", "main\x00", "", ErrInvalidRev}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + got, err := normalizeRev(tc.rev) + if !errors.Is(err, tc.wantErr) { + t.Fatalf("normalizeRev(%q) error = %v, want %v", tc.rev, err, tc.wantErr) + } + if got != tc.want { + t.Errorf("normalizeRev(%q) = %q, want %q", tc.rev, got, tc.want) + } + }) + } +} + +func TestNormalizeTreePath(t *testing.T) { + cases := []struct { + name, path, want string + wantErr error + }{ + {"empty is root", "", "", nil}, + {"dot is root", ".", "", nil}, + {"slash is root", "/", "", nil}, + {"plain", "src", "src", nil}, + {"trailing slash", "src/", "src", nil}, + {"traversal contained", "../../etc", "etc", nil}, + {"dotdot in middle", "a/../b", "b", nil}, + {"nul", "src\x00", "", ErrInvalidPath}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + got, err := normalizeTreePath(tc.path) + if !errors.Is(err, tc.wantErr) { + t.Fatalf("normalizeTreePath(%q) error = %v, want %v", tc.path, err, tc.wantErr) + } + if got != tc.want { + t.Errorf("normalizeTreePath(%q) = %q, want %q", tc.path, got, tc.want) + } + }) + } +} + +func TestParseLsTree(t *testing.T) { + // real `ls-tree --long -z` framing: size right-padded to 7, "-" for non-blobs + out := []byte("100644 blob aaaa 30\tmain.go\x00" + + "040000 tree bbbb -\tsub dir\x00" + + "100755 blob cccc 123\twith\ttab\x00") + + entries, truncated, err := parseLsTree(out, "src") + if err != nil { + t.Fatal(err) + } + if truncated { + t.Error("unexpected truncation") + } + + want := []TreeEntry{ + {Mode: "100644", Type: "blob", SHA: "aaaa", Size: 30, Path: "src/main.go"}, + {Mode: "040000", Type: "tree", SHA: "bbbb", Size: -1, Path: "src/sub dir"}, + {Mode: "100755", Type: "blob", SHA: "cccc", Size: 123, Path: "src/with\ttab"}, + } + if len(entries) != len(want) { + t.Fatalf("got %d entries, want %d: %+v", len(entries), len(want), entries) + } + for i := range want { + if entries[i] != want[i] { + t.Errorf("entry %d = %+v, want %+v", i, entries[i], want[i]) + } + } +} + +func TestParseLsTreeTruncates(t *testing.T) { + var sb strings.Builder + for i := 0; i < maxTreeEntries+5; i++ { + fmt.Fprintf(&sb, "100644 blob aaaa 1\tf%d\x00", i) + } + + entries, truncated, err := parseLsTree([]byte(sb.String()), "") + if err != nil { + t.Fatal(err) + } + if !truncated { + t.Error("want truncated listing") + } + if len(entries) != maxTreeEntries { + t.Errorf("got %d entries, want cap %d", len(entries), maxTreeEntries) + } +} + +// end-to-end against a real git binary, following the repo convention of +// skipping when git is not on PATH +func TestListTree(t *testing.T) { + if _, err := exec.LookPath("git"); err != nil { + t.Skip("git not on PATH") + } + + root := t.TempDir() + l, err := NewLocal(root) + if err != nil { + t.Fatal(err) + } + ctx := context.Background() + + if err := l.InitBare(ctx, "1/test.git"); err != nil { + t.Fatal(err) + } + + // empty repo: HEAD is unborn + if _, err := l.ListTree(ctx, "1/test.git", "", ""); !errors.Is(err, ErrRevNotFound) { + t.Fatalf("empty repo: want ErrRevNotFound, got %v", err) + } + + // build a working tree and push it to a known branch name + wt := filepath.Join(t.TempDir(), "wt") + git := func(dir string, args ...string) { + t.Helper() + cmd := exec.Command("git", append([]string{"-C", dir}, args...)...) + cmd.Env = append(os.Environ(), + "GIT_AUTHOR_NAME=t", "GIT_AUTHOR_EMAIL=t@t", + "GIT_COMMITTER_NAME=t", "GIT_COMMITTER_EMAIL=t@t", + ) + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("git %v: %v: %s", args, err, out) + } + } + git(".", "clone", filepath.Join(root, "1/test.git"), wt) + writeFile := func(rel, content string, mode os.FileMode) { + t.Helper() + full := filepath.Join(wt, rel) + if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(full, []byte(content), mode); err != nil { + t.Fatal(err) + } + } + writeFile("README.md", "hello\n", 0o644) + writeFile("src/main.go", "package main\n", 0o644) + writeFile("src/run.sh", "#!/bin/sh\n", 0o755) + git(wt, "add", "-A") + git(wt, "commit", "-m", "init") + git(wt, "push", "origin", "HEAD:refs/heads/main") + + t.Run("root listing", func(t *testing.T) { + listing, err := l.ListTree(ctx, "1/test.git", "main", "") + if err != nil { + t.Fatal(err) + } + if listing.CommitSHA == "" { + t.Error("want resolved commit sha") + } + if listing.Truncated { + t.Error("unexpected truncation") + } + if len(listing.Entries) != 2 { + t.Fatalf("want 2 entries, got %+v", listing.Entries) + } + if listing.Entries[0].Path != "README.md" || listing.Entries[0].Type != "blob" || listing.Entries[0].Size != 6 { + t.Errorf("README.md entry = %+v", listing.Entries[0]) + } + if listing.Entries[1].Path != "src" || listing.Entries[1].Type != "tree" || listing.Entries[1].Size != -1 { + t.Errorf("src entry = %+v", listing.Entries[1]) + } + }) + + t.Run("subdir listing", func(t *testing.T) { + listing, err := l.ListTree(ctx, "1/test.git", "main", "src") + if err != nil { + t.Fatal(err) + } + if len(listing.Entries) != 2 { + t.Fatalf("want 2 entries, got %+v", listing.Entries) + } + if listing.Entries[0].Path != "src/main.go" { + t.Errorf("want path src/main.go, got %q", listing.Entries[0].Path) + } + if listing.Entries[1].Mode != "100755" { + t.Errorf("run.sh: want mode 100755, got %q", listing.Entries[1].Mode) + } + }) + + t.Run("errors", func(t *testing.T) { + cases := []struct { + name, rev, path string + want error + }{ + {"unknown rev", "nope", "", ErrRevNotFound}, + {"unknown path", "main", "nope", ErrPathNotFound}, + {"path is a blob", "main", "README.md", ErrPathNotFound}, + {"hostile rev", "--help", "", ErrInvalidRev}, + {"traversal path", "main", "../../etc", ErrPathNotFound}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if _, err := l.ListTree(ctx, "1/test.git", tc.rev, tc.path); !errors.Is(err, tc.want) { + t.Errorf("ListTree(%q, %q) = %v, want %v", tc.rev, tc.path, err, tc.want) + } + }) + } + }) +} + func TestDiffRefs(t *testing.T) { cases := []struct { name string diff --git a/internal/gitbackend/types.go b/internal/gitbackend/types.go index 8479546..ed9d136 100644 --- a/internal/gitbackend/types.go +++ b/internal/gitbackend/types.go @@ -1,12 +1,38 @@ package gitbackend +import "errors" + // the all-zero object id git uses to denote a missing ref // its zero in before, if it was created after // or its zero after, if it was deleted before const zeroSHA = "0000000000000000000000000000000000000000" +// hard cap on entries returned per directory level +const maxTreeEntries = 10_000 + +var ( + ErrInvalidRev = errors.New("invalid revision") + ErrInvalidPath = errors.New("invalid tree path") + ErrRevNotFound = errors.New("revision not found") + ErrPathNotFound = errors.New("path not found in tree") +) + type RefChange struct { Ref string OldSHA string NewSHA string } + +type TreeEntry struct { + Mode string // "100644", "100755", "040000", "120000", "160000" + Type string // "blob" | "tree" | "commit" + SHA string + Size int64 // object size in bytes, -1 where git reports none (trees, submodules) + Path string // full path from the repo root +} + +type TreeListing struct { + CommitSHA string // the exact commit the listing is a snapshot of + Entries []TreeEntry + Truncated bool +} diff --git a/internal/server/control/repositories/contents.go b/internal/server/control/repositories/contents.go new file mode 100644 index 0000000..73ea467 --- /dev/null +++ b/internal/server/control/repositories/contents.go @@ -0,0 +1,43 @@ +package repositories + +import ( + "errors" + "net/http" + "strconv" + + "github.com/Axenos-dev/HeadlessGit/internal/server/response" + reposervice "github.com/Axenos-dev/HeadlessGit/internal/services/repositories" + "github.com/go-chi/chi/v5" + "go.uber.org/zap" +) + +func (h *handlers) getContents(w http.ResponseWriter, r *http.Request) error { + id, err := strconv.ParseInt(chi.URLParam(r, "repositoryID"), 10, 64) + if err != nil { + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid repository id") + } + + // ref defaults to HEAD + ref := r.URL.Query().Get("ref") + // path defaults to the repo root + treePath := r.URL.Query().Get("path") + + contents, err := h.service.Contents(r.Context(), id, ref, treePath) + switch { + case errors.Is(err, reposervice.ErrRepositoryNotFound): + return response.NewError(http.StatusNotFound, response.CodeRepositoryNotFound, "repository not found") + case errors.Is(err, reposervice.ErrRefNotFound): + return response.NewError(http.StatusNotFound, response.CodeRefNotFound, "ref not found") + case errors.Is(err, reposervice.ErrPathNotFound): + return response.NewError(http.StatusNotFound, response.CodePathNotFound, "path not found") + case errors.Is(err, reposervice.ErrInvalidRef): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid ref") + case errors.Is(err, reposervice.ErrInvalidPath): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid path") + case err != nil: + h.logger.Error("failed to list repository contents", zap.Error(err)) + return response.NewError(http.StatusInternalServerError, response.CodeInternalError, "failed to list repository contents") + } + + return response.Data(w, http.StatusOK, newContents(contents)) +} diff --git a/internal/server/control/repositories/handlers.go b/internal/server/control/repositories/handlers.go index 51affd4..c7a6709 100644 --- a/internal/server/control/repositories/handlers.go +++ b/internal/server/control/repositories/handlers.go @@ -15,6 +15,7 @@ type RepositoryManager interface { Delete(ctx context.Context, repositoryID int64) error SetVisibility(ctx context.Context, repositoryID int64, visibility domain.RepoVisibility) (domain.Repository, error) ListByOwner(ctx context.Context, ownerID int64) ([]domain.Repository, error) + Contents(ctx context.Context, repositoryID int64, ref, treePath string) (domain.RepositoryContents, error) } type handlers struct { @@ -33,6 +34,7 @@ func (h *handlers) RegisterRoutes(parent chi.Router) { parent.Route("/repositories", func(r chi.Router) { r.Post("/", response.Handler(h.logger, h.createRepository)) r.Get("/{repositoryID}", response.Handler(h.logger, h.getRepository)) + r.Get("/{repositoryID}/contents", response.Handler(h.logger, h.getContents)) r.Put("/{repositoryID}/visibility", response.Handler(h.logger, h.setVisibility)) r.Delete("/{repositoryID}", response.Handler(h.logger, h.deleteRepository)) }) diff --git a/internal/server/control/repositories/types.go b/internal/server/control/repositories/types.go index 175e626..0f5e346 100644 --- a/internal/server/control/repositories/types.go +++ b/internal/server/control/repositories/types.go @@ -54,6 +54,52 @@ func newRepositories(repos []domain.Repository) []Repository { return out } +type Contents struct { + Ref string `json:"ref"` + SHA string `json:"sha"` + Path string `json:"path"` + Entries []ContentEntry `json:"entries"` + Truncated bool `json:"truncated,omitempty"` +} + +type ContentEntry struct { + Name string `json:"name"` + Path string `json:"path"` + Type string `json:"type"` // file | dir | symlink | submodule + Mode string `json:"mode"` + Size *int64 `json:"size,omitempty"` // blobs only; note: LFS pointers report pointer size + SHA string `json:"sha"` +} + +func newContents(c domain.RepositoryContents) Contents { + entries := make([]ContentEntry, len(c.Entries)) + for i, e := range c.Entries { + entries[i] = newContentEntry(e) + } + return Contents{ + Ref: c.Ref, + SHA: c.CommitSHA, + Path: c.Path, + Entries: entries, + Truncated: c.Truncated, + } +} + +func newContentEntry(e domain.TreeEntry) ContentEntry { + entry := ContentEntry{ + Name: e.Name, + Path: e.Path, + Type: string(e.Type), + Mode: e.Mode, + SHA: e.SHA, + } + if e.Size >= 0 { + size := e.Size + entry.Size = &size + } + return entry +} + type UpdateVisibilityRequest struct { Visibility string `json:"visibility"` } diff --git a/internal/server/response/codes.go b/internal/server/response/codes.go index c907ffd..552bea5 100644 --- a/internal/server/response/codes.go +++ b/internal/server/response/codes.go @@ -10,4 +10,6 @@ const ( CodeUserNotFound = "user_not_found" CodeSSHKeyNotFound = "ssh_key_not_found" CodeTokenNotFound = "token_not_found" + CodeRefNotFound = "ref_not_found" + CodePathNotFound = "path_not_found" ) diff --git a/internal/services/repositories/errors.go b/internal/services/repositories/errors.go index 68f5765..d1f03d7 100644 --- a/internal/services/repositories/errors.go +++ b/internal/services/repositories/errors.go @@ -6,4 +6,9 @@ var ( ErrRepositoryNotFound = errors.New("repository not found") ErrInvalidRepositoryName = errors.New("invalid repository name") ErrInvalidVisibility = errors.New("invalid visibility") + + ErrRefNotFound = errors.New("ref not found") + ErrPathNotFound = errors.New("path not found") + ErrInvalidRef = errors.New("invalid ref") + ErrInvalidPath = errors.New("invalid path") ) diff --git a/internal/services/repositories/service.go b/internal/services/repositories/service.go index e9194c1..578d30e 100644 --- a/internal/services/repositories/service.go +++ b/internal/services/repositories/service.go @@ -5,11 +5,13 @@ import ( "database/sql" "errors" "fmt" + "path" "strings" "time" "github.com/Axenos-dev/HeadlessGit/internal/db/gen" "github.com/Axenos-dev/HeadlessGit/internal/domain" + "github.com/Axenos-dev/HeadlessGit/internal/gitbackend" "go.uber.org/zap" ) @@ -25,6 +27,7 @@ type Registry interface { type RepositoryStorage interface { InitBare(ctx context.Context, storagePath string) error Remove(ctx context.Context, storagePath string) error + ListTree(ctx context.Context, storagePath, rev, treePath string) (gitbackend.TreeListing, error) } type Service struct { @@ -139,6 +142,35 @@ func (s *Service) ListByOwner(ctx context.Context, ownerID int64) ([]domain.Repo return out, nil } +func (s *Service) Contents(ctx context.Context, repositoryID int64, ref, treePath string) (domain.RepositoryContents, error) { + repo, err := s.registry.GetRepository(ctx, repositoryID) + if errors.Is(err, sql.ErrNoRows) { + return domain.RepositoryContents{}, ErrRepositoryNotFound + } + if err != nil { + return domain.RepositoryContents{}, err + } + + listing, err := s.storage.ListTree(ctx, repo.StoragePath, ref, treePath) + switch { + case errors.Is(err, gitbackend.ErrInvalidRev): + return domain.RepositoryContents{}, ErrInvalidRef + case errors.Is(err, gitbackend.ErrInvalidPath): + return domain.RepositoryContents{}, ErrInvalidPath + case errors.Is(err, gitbackend.ErrRevNotFound): + return domain.RepositoryContents{}, ErrRefNotFound + case errors.Is(err, gitbackend.ErrPathNotFound): + return domain.RepositoryContents{}, ErrPathNotFound + case err != nil: + return domain.RepositoryContents{}, err + } + + if ref == "" { + ref = "HEAD" + } + return toContents(ref, treePath, listing), nil +} + func (s *Service) GetRepositoryByPath(ctx context.Context, namespace, name string) (domain.Repository, error) { repo, err := s.registry.GetRepositoryByPath(ctx, namespace, name) if errors.Is(err, sql.ErrNoRows) { @@ -172,3 +204,24 @@ func validRepositoryName(name string) bool { } return !strings.ContainsAny(name, "/\\") } + +func toContents(ref, treePath string, listing gitbackend.TreeListing) domain.RepositoryContents { + entries := make([]domain.TreeEntry, len(listing.Entries)) + for i, e := range listing.Entries { + entries[i] = domain.TreeEntry{ + Name: path.Base(e.Path), + Path: e.Path, + Type: domain.TreeEntryTypeFromMode(e.Mode), + Mode: e.Mode, + SHA: e.SHA, + Size: e.Size, + } + } + return domain.RepositoryContents{ + Ref: ref, + CommitSHA: listing.CommitSHA, + Path: treePath, + Entries: entries, + Truncated: listing.Truncated, + } +} From 245c2bc8a8d1e8a1122c14598357502610192cc6 Mon Sep 17 00:00:00 2001 From: Axenos-dev Date: Sun, 5 Jul 2026 15:33:37 -0700 Subject: [PATCH 2/7] Repository archive streaming endpoint --- AGENTS.md | 9 +- cmd/app/main.go | 43 ++-- images/achive.png | Bin 0 -> 199982 bytes internal/archive/encoder.go | 83 +++++++ internal/archive/pointer.go | 57 +++++ internal/archive/transform.go | 58 +++++ internal/archive/transform_test.go | 212 ++++++++++++++++++ internal/domain/archive.go | 46 ++++ internal/gitbackend/backend.go | 2 + internal/gitbackend/local.go | 56 ++++- internal/gitbackend/local_test.go | 128 +++++++++-- .../server/control/repositories/archive.go | 107 +++++++++ .../control/repositories/archive_test.go | 116 ++++++++++ .../server/control/repositories/handlers.go | 4 + .../control/repositories/handlers_test.go | 52 +++++ internal/server/git/githttp/e2e_test.go | 2 +- internal/server/git/githttp/lfs_e2e_test.go | 2 +- .../services/repositories/archive_test.go | 172 ++++++++++++++ internal/services/repositories/errors.go | 3 + internal/services/repositories/service.go | 84 ++++++- 20 files changed, 1191 insertions(+), 45 deletions(-) create mode 100644 images/achive.png create mode 100644 internal/archive/encoder.go create mode 100644 internal/archive/pointer.go create mode 100644 internal/archive/transform.go create mode 100644 internal/archive/transform_test.go create mode 100644 internal/domain/archive.go create mode 100644 internal/server/control/repositories/archive.go create mode 100644 internal/server/control/repositories/archive_test.go create mode 100644 internal/server/control/repositories/handlers_test.go create mode 100644 internal/services/repositories/archive_test.go diff --git a/AGENTS.md b/AGENTS.md index 14662fb..3cf9cd7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,6 +11,8 @@ It provides: - Git over SSH and HTTP (clone / fetch / push). - Git LFS (object transfer over HTTP; disk or S3 storage). - A control API to manage repositories, users, SSH keys, tokens, permissions, and webhooks. +- Read-only repo APIs on the control plane: contents listing (`ls-tree`) and + streamed zip/tar.gz archives (`git archive`, optional in-flight LFS smudging). - A `read` / `write` / `admin` permission model enforced before every Git operation. - Push webhooks, signed and delivered off the push path. @@ -52,7 +54,8 @@ Package map: | `internal/domain` | Core types (repository, account, role, token, ssh key, lfs). | | `internal/services/*` | Business logic per area (repositories, users, auth, permissions, lfs); each has a service + a registry over `db`. | | `internal/storage` | LFS object storage behind an interface (`disk`, `s3`). | -| `internal/gitbackend` | Git pack protocol behind a small interface (`Local` execs system `git`; future `RPC` to storage nodes). | +| `internal/archive` | Pure mechanism, no service deps: streaming tar re-encode to zip/tar.gz with an injected LFS smudge callback. | +| `internal/gitbackend` | Git subprocesses behind a small interface: pack protocol plus read ops (ls-tree, rev resolution, tar archive). | | `internal/server` | Composition root: wires control + git servers, runs and shuts down listeners. | | `internal/server/control` | Control API (REST); sub-handlers in `repositories/`, `users/`, `permissions/`. | | `internal/server/git/gitssh` | Git-over-SSH transport (custom in-process SSH server). | @@ -125,7 +128,9 @@ concretes once. **HTTP.** One `net/http` + `chi` stack (no `fasthttp`/Fiber: the smart-HTTP path streams bodies to/from the `git-upload-pack`/`git-receive-pack` subprocesses). The Git/LFS routes must stay streaming-safe — no body-size limits or body-buffering -middleware. Health (`/healthz`) is unauthenticated and sits outside the audit chain. +middleware; the same applies to the control API's archive route, which streams +`git archive` output. Health (`/healthz`) is unauthenticated and sits outside the +audit chain. **Logging.** `zap` structured logging. Never log secrets (tokens, webhook secrets, SSH key material, full auth headers). Each transport request emits one audit line: diff --git a/cmd/app/main.go b/cmd/app/main.go index 3ba8f65..abfb719 100644 --- a/cmd/app/main.go +++ b/cmd/app/main.go @@ -55,10 +55,35 @@ func main() { log.Fatal(err) } + // nil when LFS is disabled + var lfsService *lfs.Service + if config.LFS.Enabled { + // resolve the LFS storage, could be or disk or S3 + store, err := newLFSStorage(config.LFS) + if err != nil { + log.Fatal(err) + } + + // and initialize the service + lfsService = lfs.NewService( + root.With(zap.String("service", "lfs")), + lfs.NewRegistry(db), + store, + config.LFS.PublicURL, + ) + } + + // assign through a typed variable so a disabled LFS stays a real nil interface + var repoLFS repositories.LFSObjects + if lfsService != nil { + repoLFS = lfsService + } + repoService := repositories.NewService( root.With(zap.String("service", "repositories")), repositories.NewRegistry(db), gitBackend, + repoLFS, ) authService := auth.NewService( @@ -75,24 +100,6 @@ func main() { permsService := permissions.NewService(permissions.NewRegistry(db)) usersService := users.NewService(users.NewRegistry(db)) - // nil when LFS is disabled - var lfsService *lfs.Service - if config.LFS.Enabled { - // resolve the LFS storage, could be or disk or S3 - store, err := newLFSStorage(config.LFS) - if err != nil { - log.Fatal(err) - } - - // and initialize the service - lfsService = lfs.NewService( - root.With(zap.String("service", "lfs")), - lfs.NewRegistry(db), - store, - config.LFS.PublicURL, - ) - } - webhooksService := webhooks.NewService( root.With(zap.String("service", "webhooks")), webhooks.NewRegistry(db), diff --git a/images/achive.png b/images/achive.png new file mode 100644 index 0000000000000000000000000000000000000000..12cccf9986e82de9e1eeb5a05a734667f3af8567 GIT binary patch literal 199982 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

e)D2x^bi2%c!tlxVWap(T!zW=PplDE zv9aeg;&_;Q>PPDZOmZ2h11*94)%s_P{F)Vl6Dl#sfy4$%u15Yrgh)cRbCjy{Z%mSf z?9e2*h12CAUBvxjWrLQPdsDYaH+X2kXxc&clS1@Ru4BHAql9nyhWxuSCC@3HMLy~% zN`Y3! zQF)r7cNX!hA*5m>&NB99F{6NvowD)_iGCkanEUi%w}2P0z1Es4;l}B2H4~}wZNcMBS6Q#k{hsfkC-=k@GYqv9tqKQiLy6q2 z6L7J=WiJK+V318IDzC+YWundLKDfR9I6q?E*Kxi0Vw=3j`>!B{7H`B>Q92VYpJRlz zDUzr2CvbqZ| zUf!8c`|G9w8xug`M^2-Szy_M{QRCgI9|s3ZfiFcV-22hD1ag%^xiDO^0K4{V=%|l+ zoLv||^Yv61as@R}yX;j;sAR^&#pQe~*Rc0{O3sSjwvvU;Iocl>9% z#>xx!;~%gMcopkNK+?=@I76Q~^F5Eil4 zOKc6lrvb=cyC^zI+!#d9HF-`87DD;7Hq)|Ot-z|Di2fG=us{gyLgSE|ee(x2$@9O4 zzMKW~octrC5X&{)Lz#xTMjYG+donmZ{pn#9w%d8W7o+Dmjvrso!_NZmNUmhF$|^qo zfxIb|tkB)1sSYXZJ262C4V=@j7a)h?M&fU|IL}N0d%iI$-`T`UUqHqTs@o~E0tCXn z4C()AJqF3_9;)xsHO>7;uIb7i$`y-bu@{E?KT!*@RYSna`aCbKQlJ`PBc{WU;mgPM zNchW9U5qyp6tvn~K)lpZv66^Q8OjuQ1$k?2pm1%67#RK@0CdMdKN$S>QJ|kQ_YMAS zSlf#czcaSK52FW6veu_^!wj!qL!KBxBh_-+`M-uYa|!{O$uDRJ<$TSCh*k*v+#0MNJIrElewmqCmBZ*3zrn@Zt^l zWlTRX14U_|M-R2kV-56V z4V%IfUcOvg9q%!2pPM$Cr?T~$LtgD28T8uPDw-hmR9^A;C+rS{_|17*FCed4eT4n^ z-z2#;f|q{(XHP~4PS~yh!fmO(HjPYG;kio4qLPd}r*SRMPGM*YX|?^F0kx$OKL z4Fu~7m7frBw6)72oT0yBz#GAE?*EK}0Uaqq_mJ=My+DIpk);U9-Tw?{gT^f0nPQlB ze%(_&$nUS(-VyUDG@P@c-|z0R107mH?qqdqNdHi&0hHX(hK8S7_Z|%AKfd)(7NrD^(KZ=i` ziEQV#PQfj~1h79a=3Z?vasRH&$`^L$uZE4d2-NDm49$t(I=fAY=xbCLaIzsMx8L7L zZ>0;}>7T~D1>eNFI)J}OevKH|kv|KiJ95p+KI6C2KqwiOgA09UaI7_qQI!0PpYwvk zL0{yIj%Y3|k8sT-t!w8q6%KQWW1X(u5tGWg}U)xnqeev^mfPj=Du2B%W{LzHA9EJ;oM@B5upuPTvcfDh_Qxp@2_MsTYa5{Zv^|A4cbzuNBt#rW14b3~_vwK4VeZ=nP;oTT2-*qag&_rU+L6o!va_gy zd$9kV=exkqLY?A}{I>=k8Fq<`&9Be>VkTP-!c)15{tm%D)Y1c80|v>-=y%! zkBBp_?{BF(YY{5j2Pk1Nkp{u5sQNLjCe;Nq_mMDK;ha;`$291ym90+q7R;v{5LqwA zSIxOAMyapA4(=BjujCt4-Vh}skGK@~t(v{Pfoz={+q%oQTy1C-v!23)ToTy|xaHX} zkZ8kB?mY#!M9Azg6bU~}c<@&RKti|$W^(s5yVCCbfP|QpI>Rz1mk_#q>Q|j>i4_0; zqwKBYqTHgkVNwu|Ac}aDR8%^YlpItaEYJL5<)SW=`TCeiF;h|MyP8->@%am(g4G$iKOMh^D8xij&^O!cX1T}cf>w{(a z_PKC5wX`QyF8aCZDPaq1@V?@pktMrhfH9feKp)z99ilndcOOb7kjCBJP_= zZY_yBF@$R$|I;2E62gJ29We9jG+3_>AHCIkb>^e!bjwO)^C$1}*Q-b@cbQ6lcv3X) z0|3?s^0KDOyRX(~Nj@1yS%xv>_OJPTCl z1$ejLWG=SClS`Ij>u*y@q0eH~ToL zew!@L$!#r5OUF;Vg@pIe2qsMB==TXbb`EDgHF3aaj^3wuqk@1-{B!ICcexv2P7&v& zv4@Mn`K|`3mrm0)p&Q#y^ZzqtU>(cpkxLi4;$RE^Mb6`8Db4xC0WRQ=i4q1*xvZDG z3TU|IFYGY{9UUg9K6JYEe;xubO62sE(;nVD_zLhD+x9tcj_lQcwkeqsXE1!{?VtcQ zTN;tu|J?#p(i@wofSUZCxFr{-gBRjA7QRE5oDN#3l=t0EU+q7ehV3Wk=}&?YMgW(h z0tBm9)x7K_p@-EjK-_x3I1uh{4?wc@=|s7EUr06~Y0ue?{({ZmM8Z0K(A@{P5M1e} z;mkxH=u!pc3p{`%?46QdD!_E9Ot?Dm;z(_vJpJDTHWYi<1xOkh%|bCnrW|8L$Mh4M zrvMA#Y8=3h7pxo<1fe&argaH4ClET4`fYne%srO?RvJ}2@!z72S0ua_0O<_VAbXtX z2ldWtFAh%YTU^~)X&du<7ht~#kSr6-9{>>s_2>IblUz@-OvrdHai3JsaJ)ILISQkUy94j*`FsIjHq;6>x_YNUr7^7e%$62LWdP*+X7#r=ORRHn#cbD%1S! zjdzTj$228BS=l^)xEZl{!-S7qe4md8;tgIX+*>zYZ0@8XzCm@f#?J~Gc z%E^=ubP!&mYm~_PDBu^Vn^_7SZ&~gt_`h6hT$b_Keg}Is7yMnc?%13(-XuCA$ZYu} zB?Lyh4K;}WS#-5(r`etmZ5Ra1ABOKM;+cZ*6PYN;(IK??L3hJC2IQWWp# z0f&`V-6gQPGn_V&{!?Q^p5pBOwgyfu^{GE;2f$gYBYzhLm8cSqu0TVfn+6U$o2?@z z=^4xJN-pa5vN27+6Zwesj+m_b7r~yv+jbmhfWE!MOxRxBr)|>2w!l1jNcovT%;Wv} z{(RBs)TY48K00w~6R%+cu^56;f&Zf~^vT+UzlMASQ6=uR<7qzl-zc9pA+R8WZJnpm zV6U*l&|NI{5e5&`Ta6K3z=$Iq*Y>$AYi!B-4!A1_a)Q9w+#X9z2NolQO#ufU8P6ya z#xW$+S3=B@Epf($k?}8PnqDX9xAGJ_)X1divRoM;_=JSf9a#CG4gjFNMbAkd(bxq& zBzU*7{w>6OHNJPIeqK2LF8N}eJ*2pTGqrQ2RC?4ejK3tlu25cVu8^a74j~&qVzm%A zV&keb>u37!xx5x=y&D6Zn4Oj%#+8+ZOUZfDC~SEw%-w~nsP(g@ziFX#>qSYm>38*W zr#b%WGlgPWVo}%%^vqk_>!*~7C4jdTd-`uyR@t#vfHY(0&iksz2aXVK+GX^VyJP(r z8YjTLd_cUD z!Zdp+(pLvo^G6*$jID1T0!wsH2EF41$B&u$vPqLCUg?+veh&N(yu1JsQ7e;kcr(>M zBg(~JxAg@Od+cZT7Rk!GZ;7S+4nsRp@pDOWrHk#wK>0HMtgp&*^U%=y=GqI-+HP$& z^1(X0Kh!^%0bJzlemjW0J^zKH${9+Oz}b6*uP6xGkQO_O;zRs^uzUaQlzEVgJ*9rChFn$gWhI z3+QE3yzUpOUAf<|!)p+1w(0ue%>-gJKW*KKgcXUlXt~ zo;40<<5BkqS=6)C?wc=sZ-3@Sb8TPLL+`_F5sg1-guETBLE$-|4zl5u4k{M*7fU6j%>0Snn2!$d2js zbVHNf1b*RWvx+Ly{<%#?k3M-73k-v!Kip7V#OI|*Rb|4f%e)r?Ae<1;Z=A3X`#<3< zqzWK|TG8;#|9on~MPjdh3oee-7G35+(ryH4aaTOZl!?5!*~w_+IL?VY+e;n!Z?j(T zyHrgE1^2AhSuSML%)0!wbaa7#=auhfw7tydi^Da)9-KAv8=yw(=_nLjnqsFPeZknlxn=&X($agLZ}KkL)YX06zpTL)JV*DP*viq2b#=UN?xqZF2dNTA-)hOw zZ;$6Q0fz62+||uOwaib12-=s1N2@IqKC@v7?sMw|!mDesM~(p^>SV+lgw5XH=zGcE zLz2$fv#Q)+^B@t%)omY905x;JjR(-Y4u2=iG!CM=XewIl8%Dlko_2l6&EIf_cJZ~g zsukusau0Qs3^_mY4uK--cM44{>_;7SEQ#TlDGT;VgNErjBb6vBcf^BB*AK{wfh3BO zFr9&`QbkDUo^$(i+X1sy!1I&!h?+U*-0>64L1@G2CA2_+UGrRZ@ZzW7PclWPJlK#rQYaoez9>Y(W=^=vdkRQM_4kS z6sjzx6|UepRsbHA1#7OYibim#EEJ~$kZ*6soJ;ZR?Mv5ukfIJ-`ghD*nFdTx@AJGs zl50p@2{zIGiksw;pWhWM>&gATcJvzEKbzYeC;NYXQmwmOA!9J&^cH5=)KGsiPV8=B zf75v?J>D*s1Rd4{p1xnN8Tx10i`8`OS^vGb>5}X7@&RTP60F`Jv~k+l>H; z{TBivPLM8cSWw*g@F_zyu4ihBGeibdwC-Jm1rsE~Krpp<+qNhg&uD)R-v9lc{6I>{ zGeF>V>4IR{sOkgd)_YlMvr5>`jT?MICkHztP>Nh{_?ZVx7pMWLlGuC!reyv>>iAuS zl0`|?zYCTgrnuQi;+*Y0$p=EGLrP3@0EDBz4|e2YqUHwv;1rxEKH|6Nq}Kcvi~|j%1;TdM zRjezbq2gb9?2<5gi1cxzy&xiy-GBt_D!3fzx zN#VcRPhGd>P{CbQMcltJ-k%c2D0LkL~Ag=o@t$E@R(#oen1kOg){-EX&7Y8G^J_8g+s3yEVF+I)Dp%8YFr9^>yG~DK= zYK6CTI`eOZb62KGHYb2mDC3}*WIHm=Kf}k)I1tFZ+689Z4wVbk(1Dl3Wln)yhKxkN zE3mc7c?y6$t$k&7uYM(o=DInFyOVIcSzk$X;uaC$TKN3PSGVsS=ksqTq8t9u_Els> zr`|^ji0B<;9}X-p9y*i%y>bd~4_IFSgQBK?eke9efPs?WMG!PseKja;P`d3C4A{YT zd^%sT+#`@&;9j$SigP@>tOS>Hs}CY-ITXPCp9sML5C^+YPnQ!3#~iKGq~dK$$)kJU z&2CNeUn3gAL%c_6a5%bs6ye^$9+!MLM)-*Ek^||-zq~%S2Gnd<(v^T<=2`FMw|nbJ z7}p#wLNV-ev*~1g>=AC~|M5sT;^ZAxuMZ4$6QFSbLDz3{LXs+Qt0$(BNpR8j{}NDQ z&K-(1_=A4|Y2BH+tL)a7F9Jp<$Xl|h{p%Zc1w0@r!Ks|EZ!RR2M>iI)sDSe?E#&)v zfD6E5g$Sbnl6eMr7)8!ktQF|Ur|_}ceeJe4)V)X)?pJMYaMxS8z-$T9GwhupBFqG$ zOiV?mg8*J?_7!|Z?coZ7{8v}VA5X*0{veVM?mlzy?&rSl)BA|QCOVTtTah3KRFTnZfeLWmcW>TU&~(#KrwB-$-Yq%p?a{m2ZQ_H0yZF?fG;*)0w#`L;@Km_ z?#utyw5dv(RN`1v3A>0N2D}!aPE&u4rafYE9$?z}}P;KnVM4vrF$+{?Ql?B@T|1c*qeaUmokn(QNEtq&*q z4@n>R@K51}`{Lxb6>~cqoKsNMJobUGTnBr#pXNVD2ON~itIy6|KP!ABL=W$#G8epK zhcJBT|34;LUq!@s7?{%u27EJ$HQ*YX65THahd7W~gC5I3HR5t@+#e6!v1Ct@M%Cf4|qM;)JUd-^tx@`jy`89~bK{-ZLQf{=?J9ZzJw_F@uXJ+brS;(JB7C z1H$DQ9wdkv&Fj&Y0&^(uCFNW1I)E4jQqO*8-wQkt!TwXpB71_djH4Rfc8Z!Nbh_K4 znZ>WS4m;e4?Cz5kYf#LIylpsMurEsmSdua*fV(#=2*!C_&X6t@6h7Q(BKR8|?@#gR z+b$SxNX37yivh|@>;Q4B0Y&P&KkDSv6D{ei#g_mjoK3#{zweHT1qkTnHorpsAr5c^ z-B<=C{arR17OxL4^DYD5qsjBuL#HbZog%+;vpK4&BDt~@avUkF$0qN3@T`-Eq_ILYH_Z%$a zIz4c-w^5u)%*oyRYlGX2SDA$L{zY`vXz{+^4z>$xxtY+2BuWvbvXf{#sKC ztkF_u-8`_s!P9E=sGR_j(%$hoO2~qrrW1}-YVR<@^N#<;xA^**GPI_Pg;8kVD$ThS z03&>Za7w4b!0Zek8!94>q$BsH38|+3huy@j@gb*Kh{T*mbq1k9-Nwyi4Q}S&iC-TL z72a1s$q+c_T(tuRaEi(j{=kL!Xc;S8s1LCO?xDX_**q_OM`lVRvlv57leO>VAHAnR zMAwz@4v^|o0Fp93W!{eK8_K3nQbLI8fhoYh9si3wM9M%VS6wAULIWkW;Utnghr3$; zCi@?&-gX>rPhsQs?pfE7JW|am@*jQt`aja_@dvX_5uR3F`?}zLLO|`tTGfhc% zf>>Lb?l@`1bROVU0DPhA4|G&4kb9of>G0cZ|5G9IDgYG1`W?MQUZ!(R4E`c7D^tBa zyT1Rhw1-3L$TIM^P4XtmBPNdO1#3Uu)sU|^tC}FifF`P824^HBu=@PRs#?Askh1(5 zA{f_$)M7Wcfq9! z^&00r+RwJVNCvn;!yN-OGM%6>3BjvF8ARbEWOah6aFl#XcJIlQ=0Mmr-*eDqq>GosxL!ZZ~ytV9&+pbzEn6o23zjKHwyb1) zwdi%%){@9e(JI;3K|fGn@!Thyq9DaOM1S!UqRixo=oQa4cT6H3vmF;4$)Nl8tfiuOhdF z119|!lnU*7Hw3k-E?6H;WKdHT;7=u9{sAO{%*JB-uXY@!ij9`!Xqy2zKhD z)dr7(>)w=vHt#(Q_Z{-ne*>`S+Av4(PhrpD{ojXL5f9*S2g@lqv&6G!T8JReZKEX1 z_<$i>9m#$3imt5*x=V4AErg_e(cgh(P$eF(m+7rP=$@0JDWv6^x(0IixkL&$`Sj+w#~n$jy1;i`VGmz| zU%;AXiNJd^cSXAXxR3GkHKa@K@FHm+veq-bF2-~71fVU(@AbXEK`8e8j!^sBnt1gp z{lr`c9T;D-VgSAY4Ddlf+HFn!F2#Ye{6gMGf}aBX4P{9s*Y%Q4y(mUN?MzUn$A}pS zKjXe;g2pK`NuS`Ckm}=Y#(Up$257pT-?EV|olba}q6hU4I-i~f@J6EfJxixqNDdHq z%=AIPf7dglmp@TWkve{)J_R2tDkA~1s}=B-pRlJyBu~y{>@HRmNWV7&)UyGq%f&=; zy4$|k>3zV%Hs8s*MT>1d$O1s69Y$8a;8IFDli?%#QUXaQJ1`Qiu?v=Te*Mvh+%#xV z2nA49wI(wh*mHlHCYMRhjaa$5M(o}(Kgz?-84N__%k}8xOV3Dzafm_O3SHv}9a)~F z{T?eRg6ov9VF>Pu)X{c^x+tk1f(c+9ukk}Ldk@z67i4ImYo(x#a@MX)N!Ui;p+$kG zV5@mZlKMsTkG$YECt!Ivzw@_4<;i*^QSQy;d@?B$yPq^KgstcS$QXkM83X09!vLHt zjyu`a0>s`S0o0-UQvo6jRLt71_Wk~C-aIw!xXcgJpv9Mk%l`pCFq|?md`jj{4pqE; z>co-wD%c9hH?ZlA{l|HHU4YvPegQ2z&q0U<;B*M!2LHaRWO*qUA$=A{5)LHpNOG8g z9-P4O(f0=lU=W4^WfsYDK*b-UIVxT;r-Lp^dhplz;5pL{g#c(Z?Y&b63IJ+%H6nT) z0H6bK4W<&l12G~~^0MJX@A-{*MlND9sw-fpYh}H~w&aEm6#{NT)l_YcWIYBZzP?gh zt21$>&yF2cC;QCjx*@A$PJ|Z_kw`OS?0)yL4WT0dB)!>d?(eTO5&Rh3@MFh3n;I?z zg_8_td=shUBpd{PvRG}DaNvl^CXRnD?A~2tmS@mAl<4OK__>%pf4lwfgLmjFJ zj>R=EJ!^Wf)}hA4dN|ef%P@KU^|P00k*h*Vn}<&?zW_lX^!`6BYvO_zP5+vP;3ofzx6S`UBGXZKrX&?}#(X;?-65NFnhHGC^I! z|F0SKE@dLwZpp|s##EL&6Cd@IqGxVf8E@0tt$4(5FgJ~LJPC6whLmf}o)4Qr^VHcJ zG?d`gQ*u1XMt{_n>Q9U+lfsH;f#;{z)`8Ye9So9d%L_dyBH*JN8a4{u(oq_eXm^;w z@4&?Z9u9Q#eIXlef^r9|X$L}}Jp)Okdf;dIv&sJW1ur}OTY=>%T(8_Kra?9|JHhOc zeT8&)XsMU}_SZBA^I)&6NFjZl8pjRMOCAwP(R`JYBzA5rTVLG<W|<3J)zX zKocxQq=Zri)Wl*2Lf4DJN;^BhGBc2W)JtQGt&r+=sI@FYFBz`9uVT$u8EoyoVbfiw zr%GP#^=72N$hy=uKFUSbKhf5WPeX0cttvkczM%pg504+@o2XJ5eD5vcd?J%&m$yY3 zDp~W~i-ex7EuREkB^%cmKBg6kh}-l)KVR2K4;h*o4M$fggge6=@w4CF1XVINH%k^` zW}s)75FOmwPg7S4ImC8rs2vUD9Ja;AooGrx1T%3amP zogz4a7Zv^xgqt**F-rLd=Pi<|z?kh`g-uMvt=H&|SM8d^V=CM;KL*=W8SQ9#mOgn6 zb~46R8I)+uuDY+l-qPE^n%-k7QJN1>exzRV237ep&9x`aR9i~(_0W!{L6_{T5xv#M zfm!JmzaQu8D?MP;V&+Ygkh;TLmYKixeBy;EzZ)ue0s3e)b-vaeb}7_|l_$aDabrks zYZ}FsT=C3cO@D{(r}C_J`kQ`=BoUF0BCB;1xf7U)P45{pwC#+}V(S&=u2q#V0F+JA zr8y(?=zHELa?GOoNN zKLqj<{xFwBJjy_8lPNb#E$h?Z>r3O|be>U?t2?~idEM><)n4YwXUKnKBx;UIElYIm zo?(_9Zk@I6ZXJ*4p3!SxZ>wtXOR#;GxB6>CXL@Kb1(~xZu>#xfTf#_az0s)4di(~( zYe^F{=cWSHg~RbbU$&ni{5EP3~SKn#o#hxpwb-t6QSnQ!ysx@xC`sw9`iE@7u?dl1Rt z8z(+Qvee2p@eG$DlS)6TL))dQ=YF9xRvNUHmS89vbj6(6vrSKCqv%F0;co1TXpZ%+ zYkE!zJ5=r1ME1rI|M$&Lvb~BOt1%R%NM)9oUxT?pp9kMA+@N)~J?EM2W>em*Ye;b<=($I<=xW4Mrv>^0EX4aJkUUllX!oU^g;Gb(nmpCHcv=;96>@9*a5#V2V?IXbsoFglyOmYybC^+z(4IpB~opscgiB(yKBI=T_ ztfZJOA1~w(6Gh1;_HdghM`g31Zo^D(0N^<6m{h=(btca0xiX43*44jUil;s@^g-PI zk>hwlo{lhBaN~6flGnD`{pF(qQ<^chVGG6@Yo1gc2##ct9nQar{vD9?`Q}QlYZW)G z?4xVP^YN3N(OGfRvwPuhsr9Ck=0PA4_1^CA%CoI|Og<1bXT)h#ym11*OV!3nrUyj2 zJM78PJcAzfRNATzll~F~Mld6DrKg{NrOJND)bFSN$GQvdk^xF9Aq`6plC1Q31#(jo zD0A*YMvwDQeb()7pIAV2{7m0$$$t&vpL?%iVQVp0}jW^?f6z_ixPr^#Nd} zJ|0-pUXo@d`z?ETaou@041oFk>Pum_g3`Yi2N7EA_uOVQJd;G{3ohv>!;~MlRXQxh zccjYgN=W?Z?qV5C+wh1rnl{k=BjsHGm+i1nFISkF9pwh<|{!*`;ODr8ztLun--*J+r0$t|VL z`OM1R$K4}>l)ljXhgNy{#Wr!8%#ru+tFYgd41hVfJ#^h9# zk6VMIUWo-`%%TTUVd0>|UL(n|&~uL9i?LR<}M2 zvORiBYC^W0N+wIwP(QnY!g0@#eg(DrQ2_n zNaLmMC~{%o`ZI&XsfBvGaiqwwx-(g7g&RNM)@CDoe>X*x zV!hJDm7cUG;AAA`!1Y_e8JrdBs?QEBVebpT`tN8@M~c0IjLYdK>WQ!)AL*c?{l_-4 zBuhyBg`OU>qmeGX?x~=041-(O3*YT77R)xZP&+#y{|naiXjlVS-BxfX`dmQOh4z}K zhPL9IvAx3tPE9wgl(!bH)*E<13UXK|26sSPdWT$P#_sM99gzoeq4x;aR@} z@`P;)+12%o#npIdnmT;T9U5E~0$0n1X;?m=$-(?2djaM{c(yZ$L4jyUED3@r*PNaY zU9SJ{AxaW_X#>JG3332VPp9@-x4@b}zLQJEaNRL$>;+cf1hJvb^O863J>B4jGPRm6 zN(u2zupxBL;56sjDm)$$lH-IttBCIk#maz3q@n#$N^%w|dcVn&0n z!2-G+PK2|}0Ie|qVQ+4AND@vv5j>UZm%SvdJ=Fv03}p*5#z8Xo%u3AwZHdR);`t%J z#^tn?PR!owX3}u0DP7#yUel`{6Gqg1&B1o~ZRIbl&X!1_&9Le_i~ChgL3X&RGt z5LZ2&jPON%o0kJg2*M3RnS*P{YDd;;3btOBd`e{R6zZPDfu$J~PskaMSOOZCj#MST zn;&;4OV6f%)Ez|02pq=Abm?M7>s*j98TlG>w3puzIy)*s&5ZqlirsRT~gfIxiMf> zc`pLkD>%1sa#*T#58l8RUHOI7RTgAi5{ad$3JFpn}AU4reHs9l1oT>p@3@ zsT?B2N=m?J+j0%>Wmd0uDIayWrxcS81qJL$H94+a>It!)CDI4@wPw4z^0^O>;7^I* zdAKSHw}&)f8IJ_&fE)a}hSza4>-M)LDgs8lZIT4Fu!CF<1vuPPuL+!336M)cvh{MW zgox)bdx(Wx&ruY_oq8Rh=cwCWpv4J zkL;(pd@|^-=M|vU#zIm;@>db~=nyIluf!#rdxaDTSw0g!GVv=UWehr&CR!zro#ow-BqapW#*?5UHid;(+=yK? zH^BEqXH9IR_(#xk+-{)~*{|_$b0fwr9>|6X6Z=~T>c)W&pOCa@VF9uI z)Smg>fQh|x8_Gyb`)x^qabrriqlU8TSiIs);DNz0QFJ+rvnSjqlz#D0Ma4?EEzzeb8j`Qu|oGOUW_<$_iSc)n1 z4fSWLz{0PUL+Z3~fL--KE%)fu1j_e(IKB<@^d8kF+3`|V_-1?N&3KBH%H6y63q14^ z1TYPL3QZsyX{T$@-ygGIjeVfU%(cfhl;^spVOYh~q}Dk^b&CV&KF~wHkqX1%9#?eN zXEUX-`r92=8~@fQk#|5|gVv6lW<9=MscwZJSHjCXmLx#itR(B$@=+Io^6+tDNU`b` zj@h?sYMztzfow^9e+OdzF{XT$^Mu?cPa{f|>Em@MV_-BQM28NTlazKKoC;33D z9VMqI{~gM(=E?Q6qgnEtNXR1`!A|HO1Uoq4I!Vd2qg;`|u#ifxn*M}3yP=M?7~VaX zvgs7B;Tp1$q^KPF&64qAu;91LB3Ty(GXZv+p1r2 zzj&+9cZX2T3!xE#XZ@}OT~$|Hf0791TU+>ar7-=$-_ce;M#Ri~a%?1chXc%RWg!6WkpmI0e22TuKu zH@fGd5raWty5>M5>QbZ^F$4wAGu6G#VQqL>Zx z4X5@ZL<#e-5v^TC}T6J)ZFHF}BY@#1rTle1m3$%j10M|WE?T8;v?5X6d_#eDLK9y&| zDinJl>-etUuJ?gYLswu?X<*_Vf_~Y|UtGU)jk|wb$Y+k&C^4O09{aQa)gFN2HJCTw zv2rX>m(XQ(yHH?B@_IORy00!SO7|99DT&S4o%6zB$6k6q0~qtMk8F`jmz79w06xie zRK4c~LE{=(<-}!OrQ3B%frS9G9l^Wno5{d>+0KK{ac3R#e(BPJi*em#+vUf%{_rEp zuK?ZGYn=%&(@{J%*!}edRg3^(ixo!>D-CX@_b$8Mhu810^`+4(V4q~ZfToQ95-ILw zNl6>g!14IkiPEe#!OoH2-Q&Dv{R`tU$KrL{GErDYspHGF3Vp( zGOx3J2DdZ>$bxKQ5SYikKT1F=@0B@C6M)A^ZD@G#-5)B-jC!3@E%+GA; zrs4u9BG>9=5~V^fonZU--BbVvE#+c+k+9HGNvvu! zN;jP%qgud*Y+>Gy56i4tjCZ~+jG~Xw%+&b0##DYDHzUq}h!XbQWNloIX2!K$hj5z* z6YWtPOqD>U$$Xs6vBL!;eRJQwJ8NOoH|JJc=Ke}`-IxMAw-lXEx|{Q>KdY{o08_%{ zlef8xqDGOUzWKs~9p9E#j2C@Be~YY`%YB)-TA9}i`tXTrHMd{IouzTEzKIaAz*_0P z&!l&yGCq?QOUaX2wn$RY(*sGOwgFuS%@VhYUti%XJyE;Vs=^)N=U4KE%rwoF1vR7KVXY;X?zMX;K>MYVi)R5MC zIj$aX*{H%|EU3j(P|FsH)^i_8q#(8`ljuLF!HO*>XbM1L#IKHTMfuc$IK-Vm4$8Z((Mwf@V&w`Nsx;bgW}n(npB zaypHdF;8X|TMbhgLL>dKYg>x@HPSdsgw2PfBx3;-0#Np>G7%m6F}R<;&`-JLTVeq2ka`)W0D4DHUAv#|oz$I<@lg4N5DK)w!7kRwN zVZ*NCQ=dfg)3&??(^nsts<`wRy+pT$x@&MvZV zBy0IbYB4D2`TW4$;G3w7MD({&H!Z~Oo6J7R4w%1R;jrT5CaFZVtVX%FZ9YtEayz7R z1(oPS6iX4-GFKSAVaC>-=C8Gp*l|Lsm}M<(J>*B67u?u2Z0C~1DlH>uy;DtZo-HA@z> z@0ZFzO9p+`3$D?<`Hwez3r%?QIkqdo^|bUd>@oxwQDUQKBY>y+&$NyD77vOa@L86f zN-o4}OBnYUoDtOc)(QEb&$rNWGr!8lrf?Rmezu(Ck(Lu)eIQ|IlMtrHF%Yo*ua#CD z%>trA1&vr>k+hV3^>DMNTz?J_{ALce0y`GNh#iy$Rm+{O^E*12bZ?^8t}n>;fyyjW ztg>Dta(1zCu$jeYqFpz8%2!soX~(niK4Ny!*$cDG;uF&tC9Sehx@j}2oh5xXdnete zp#4VVU3BrL_2#TAdVR$MefJBfFxe3bo^#|a!jvqqN6x1SzmM4A`(4uKx8-MDY7R>ImCjRDKBO(C}&))^)Zc+IT8ECP?D4UOkNwO4seSC!~ckgCMdyM0{alo)K&|X>`qsvCUGwI4%d~~}x zt58rsEx_2AI@S5)y~v4eZ~Mp+83$FrVNni|N7`{)aWvtLv*E@+O*@`@j{%jwG*D{^AqeNQB{c%dCk>jI|@5uYle+16T z&fM7*j2)zD`|Wo+xqAN!#ybe1B5*M2GTYAB!hXw^)_dnQ^ct6+q}q4c#^WkQv-(#r z7Q580==p_4&Qa_6qnB9*&*#nF_WK>Q{c0w6RqQ!BFyU``Wj8&0g{rrHM-MYEf zE3}%}TtTV5?~`qDE}gG~T{4^7u`p51tN{<#a{xp7J3AF_kST4uAhrf~r z|EQNqhRz;q>`k{eSv0vwZPZ)+5jiyk8_vQefy$)r#OUlD+Ex~blDj=27EpN8cEPMu zWs*GX3-&y;T5)!J17iZQIGglNZnN=+J|FA_&a=7Sy|rk`-m`&_n?y4%#;@t$=0GX-Pyy2Bf|jvcj)(PNN_kLqI&8O_ zln1d@t;8z5ZjKo%`|0xqn_BjyXQAAE_cqKoe4}^%!)jFPXz56W(ZHfzsgY2u0ktqi zlPB9tiYQNr;y|Hr=q-zA8^cpI%@8(5Z5l4Id2f}^ zDwWTN5v4oj+2ynRqMtytR5s-IPP~5=HpZRgBd8G<7p>_bJ*6~zccqIozp{l}d0@gz zZMq1XU8-i$@E$fvZo2*mfZ2XED12UeF9p~6_wPN^6UYig_IR5%*@iOCzmphU{=>L? zKs>>GI>=0NAgyRtW2e1-t~gFiZ5Oe415>vy61`b}S1kz?H`}hR)y8gPvj+gvBehDp ze#6e>#FPBxz1wjIRbF9%iImn)!{qt7{jTEDGy==<~#2BxlP- z)WBp{W6-_5zsqP71t-QR2+JgY`5NeahXo#8;@^{&w%TXciGEifoVIRaq`9Mnm_*0< zpyEXC=Cgug)ZCi_h}lQBbsX_on@@vxB_h|Y?Fzns!EdUn>TLWQ5a^z!#79Os*r6V z&{?&T%+s398>^vqb5Jv;q&FlXt&v1d=jTfZ$2D+oO~n#X99Uu3F5cU{X?uI%rqF(9 zE`lgwpLmOv41`ctg-b*7f!~bY2M2I5on+GlsH5kG$zbIJcrX)HbeagdL^n5XU)`yYm`Z-=c0XtmGtwHQBUd*<1 zz*Lij8tc6c3W0kPh35yWzp@q+kI$;p>;FCH`c7-DUNf#=fEW49vCnk1??Wf{FLc3K zo?T+&!U$nhU1Ivqnw#s8%TBQD>TBc-I%H1Gv9fP#@r9_kiU0ebK9Ih%d_`iMyY(m1 z`~EFIwqSobUPH5m*ug)=&Hvp}@Lgb#UP3gHmVm#!=z|PiB=Xvdo$zRb2UB#*PlP}; z?tgN%fN>Q`-ZeB|)dC@AsL^78biP+4(`cH@TD;0QYbWxiSk#<(*xjKV3H=_B~|vi~XIX;)T1QxYTy=DOVh#NyDkU zBaDN1q{H^-r_DLJYczpuj#*K2BSo;HJVbOhY}}-}<9m3n=_QndVa3O*4HG&hfIBqs zp49KgsLkgLltt6s5{Q1;XvLY&S3hk?yk58!&ybyR8f}mhEc`p8duSD^nv28~IaP=U z&&p}o7|n(&!c-q;)|P3_QITd#Em$N|Vgb5gn(y=GaQ>IApUrD%B%+F}hOVKF^6bibT%AvP@CuHucBnLo`DMo_usJEm~pA z{b0@*~7mArFDVZll|@BewKKVEAvCE$kD!awBVDG1G8^}UiYKsp6=|IbJL9cCA4Wx zAOsNGnDj2Z?$c9&0{sa8Crq^KdP%I(?S8+!)Vk|cSG?3Www}h@dwx>gZ1X-xi>lqR0}0hk zN5)?pH=wiZx;AO8p7yL%q!-gyV=6|Qw0k~IuTBf;#Su)Q`{q4JG)-liRH$7RgnXhP#uIGs*6-dtK;;j zV{Z5Wn%Git=9YdfkUZlIm8@!Zb$WRWNgM-rr`+lM@#bv_n`pi6;y2Jw+tIVBexhXB zsZCiz$A^?BSxnBPDM2H$UFYFirVqSMxsGEN_1Yp^HCay+0>J?g5AqBEFQno5 zGyLA}sE8GOAkqh3CLHW_{G;xj`yxHN!{=fRD<3JG%6a#rM?KTLnzF~9W=T=YEivBQ z)-jbGTZgc}RxzxM{>>*gkWz9oco|dT9`dx)ohR;C7S=;Wa_1FAnnPcqK6*AZldI+Pk#->SBe@hv{;;O}P(D6IR$*3iLlAUvj<{ zZes!Y!@N^P_XN(n*Yq*&xTj|Cm^5Iwu*!BdbvKB8vwCIa^{{W>T+xOzpZasCGT&_R z;B+oaSL%i_h!M`nzPbTPi^+h^J-uA<}%cN5+3V zDO`ArCo#debYT0XYr3lp?6oxaHAxP`9^W=4to*rZ8}B5PpJl#bN|95w?dENAW)x$C&@Ljizitj%rz zBhE@tVzimdiLBOE_~h?W<@||;npHEc8j^#oy`j>Fhx1U$_#Zax^ z;`;|r@|q1`Ev7}|SS3a6X#1St!^ys|B?XGxmb6)Cn=O!HvP<{A$ZCW1dOv2Cx~X|< z!B6sL#hXl5-{*7FKoKdtmN1H%cu389THI|AgXWmda?0D;MQm&>CC|kSl)48Etu_t6U>Mmf=6E@J{JfY=FT9jmT?=#v`EIKV8a zRm9N^DE!^#2B3K{<6BgoZAu{BBE@+d^?U4GORyRX=lj%OLK$T?gHLOsd3m3~uP4+4 zxljl*IGbHJ+NC1OGs0HwDee4ba9 zk}s@ScnFIm2x8z3gk0GZb)kU?xsWQcu2%vsGTj}3iGjYg&QzKZTki-lo%p{qDfBms3FbVZ!M zk9P=4^qi)`Ah09inC~m4dG`1XKGvomTx|E!$lH)jl`wj1|A{`Nzx*jl@zd8{aXoxq zi@&{nB1LHeb@K)bI{EMGI;Pdnu(N%!#60%?wd!( zmlQ9j_5|3c3HmyQ;5!!H!&wokE7CX(9yG<+ggw zP>8hyv1ZZYKZS`+dtK){n0h7Q+3&cmbU-oTP|hzM^E*<4)epVUuDM-*;_Se`8@y}v z>gcSIp^_i7EIIeT(kSBTnMrLKYY*zW&zf(94WC3T;y zR2xS=^vQjx*10~KCt;MbO#EW5HS2Ok?^9;?uTQDxl%S&ydRW9@-o?fjd}DGqSqjEe z*lqHZhbjBGv0UjMKo5f&1orr;8A2?8psRs}I8_eW4lyv4Jw<`n-`4DqtAy)4)SsBv zx3Etp413F?gtq0|K!Q~^5?m)RXYYLGMCpgUUkYK6L20!?=^KM@Qr1y?MY7Tcg-*in ze#$Yw7LlRKH!tm$`TlD+4;DDXy2_ReqQ|&krj0ks@Vo>4m!7`^PURUq90`df!lSPQBxuKl!LuWM^8-Nq3-CmXo3qR^phpC3PB2HN<=gh-re8E7p@0L^2f z?y_o0?S_2D0Mp&)k|5|wYrrL19vD#=2}!<_MJgLJvS8FFa*=8aJgdF zz9BKAyh;Mq>+nh$dlRvqkC;CaO+#pJ7>eGBCg8{RHuH=DPCcc8a`v z8dDseSoK-+zS}Q&uPw?~sD6RG*xNeq_jMG_ovQ_bMEibzte6TyHUR zFP

XE~2clu-!v)O~>1khCHqu^7-@88(^ORixSI_BwP{@nQ>c6us1>$Xj$W43EyS z+uNx90qw&}4Ce>P=KK@?G5hK>c1Pq2cS*3gm4y*#6$XZQX6C;O zvQz41EDELDn`_(COZo&`nE3mNC3mO--D{ICsTASyu4Z4>@Df-+C!5m zy<;tPhNDy9M;7XOL+%gs`xW=s?zADh7PM9Obz85j@ci{|-GcVc3$qt#*ugSV&CTb` zjtyOHPq1j$`}RNpQ{=`;l@O)qZ)uXAC#QshnRR18W6Y_*`tMDSuv zuDWiMViIQZtEE3(4)62_|49B>@kbg(qg~FP{0QsW?g^KY1xvn&i1Sx+Hy`K-7Wa;1 zK~aeXYb+8Az54c!omfBV5@@w`Oha9mRTxPF@Z{@S&2LdWAVq)HtQiEkC2{&JizpaBBezO5m~C6wX%h5GrCG;iELwuQ9?{o z#?H(nNgFDLtfTDfWZ#E2N|@|BNoK5L8H_Q;{9e;?>+}8HKkmc5P3HZ6z0T{L=Xsvz z>l}GR+rvHB&^J&ULrK2&Rrzs94&v*FjR!^Hnm5MS-G-XlKlMn_rOOb{4RgzT#T*M! z#a%fmGZ|TKwEk6I#%+_bnLKEQvF{j5y0f2fOy)Xc25D=NyRVmaRZ`rY2<;)s7 z9GKZUS?uiMZq@U3#Zu%%x?vf<-A7F(y#qg)XxKVaK5{;!G>9wvonT)G*sJMiLbjKI z>z53d?g8xNMWxlKlOBc4)1Z}+x{nBhM}ST~udF%VpzTxTvgH3rZSWd7%NVyX?v#cb zLFXPNd%fE=kkEUQa`}0eq(IWk@2BDMT^YUTj4}uY7*4m%1tnXSXSL<*spw+|F>*4~ z7mEA&`&vQxK1%RvGMIJgC!>;$O|KcBCv8}k&aWv~Mtqtt5|IaWx~}8`kkushIYzRZ zD}JdGmuXp>K*?&_XSOVNl*4T1`?~@px%LapJLKQGmk+dfT$)VG3WbYM@QT7(Z8mBz zDk&rT7D=PX)xk~?{Jk8fz>?4|fuDc`p6-*$h~C@{EuJ2judxmJ<#;A#7! z#Oec1qi4KU{mw6s32ZOYSpPMftBlsjQ z#~Vr}wHH}wpZ(9y*aQa~cS?%~pKkew0gc!>WiI?*x&KEls=M!X_bT*qyn?ume4@ok z&Q`A_#h4Q12A=&W%h3CuV&hQQh)V%uX$CE7i?y$gVHMEaNfZH(z0MXFM*>;CdCJB{ zRn3VhV`%Q=LF@~k0|>N*nN!3IuS$Am{|cdt!!S4fNDaLmPhzX_`{B4O!OU|Db(wa0?oaO3JMwHlavN`GD-4#jrO-kDf!i$bJ*X(HPxsbwWA4~7}OcnCTWDu+AbDvv+ ziBe9&G*x0JrEllO(apiZyi0<4qdECdXPk#upq95zbi{~{tDK-DT zrw<$&=oH5u9MWzSAem9{-|UqeCRdUe=iIo9q-S zg6S2LbQ|LG-;@U3Y~I`&kDsEiVy0ZyqYYYQ2)Jjwc^$>5kOJCO$7Y}OnU*+ak=(0V zQQ&QN4T#c;wogC8--|A6eSsddtje)-33j< z@DW%)%$4;0C~0PJZqEp=Vcr6BdA9NM#*2F@Qj9ry6rQ-?t>N=6&7j$60YQr4tLPle zCQqBREFi1Y>ddR!4p4W_)?Fe)jcN0wL1bQX;f2^ZUGL$CRV3GiG2xE%jY_j5zP)Dq z-M3*^E;W@im9YvQJNZ@-Ymk{u$wTu8J-O~5-o53<(Y@R1^hdCTkeHn2DVu*CbTsy|C4AJ%!%* z{d4nZl)MT<4r=0hzda%Im||VwXG5}yq$1efY?;^>18W-P4RP9|w-Mo*Up^6_H>B5^d(Ta~AA6f2x zA%DPS{{;EVo{aZ;b#*ChniF8)|bzc&zWua5WxpYy{y4HGU1-B_RB@oKrpce@F`Hs~j#y8ZLg^Bd9eu5qbV)HQ9dtFs9W)3?Pl)%2S;JWrYO^09%c#CsDY~@7?~%H z`1PZWAN0pM?3|01bII07Pg$oaNjtZkamFiP#Rih{isixtS^IjMVw>>{y)dl05vuz^sFTmjgPq`~rHp#-JsM2ldg*3UT@2#n3B}H9A28#AkIjP}oN<1U=<=ZpM|@ zF^?p9yRUj5C!YS-A&gN2d&Am!<+1N{Oq|=S6!xwW>rkq?^n9?6`c{Ro zM}i-@ZiK$Exl+GB7h$m;#qpnBnf=w#*iBKVC61)9%Hm|6{Zixp{y=n+&Vh^9k*B1{ zhD*FPuM57=fy)#0PU<=3Xs=0EqKb!7a2r+J$s2e5znnrQd6Tv?j1;Dal#~k?4-}2( zTw2X58Fg?g>frmMlDwVDLF`}ebol8uunhT1l{mwnK_<9x_t*Ge{J6bAxWYzb7FmAhOYhq=$${Q`Dx{8=;GnZ$X<(Mv}WXMp!{ zoa$PjV&CR(Ol~82PzEv@=oTe=Nl~L5L)7YbN}w0Lgh>Hs+@0ghkIFC`M9($Srzx8Q zTZY$h0K!Xx!-LOeo}|Q?fV?wZ#8ERr@{J<#QnNL@?*iUa`nvyHYrv8m&Frw z-ln%a?}dEW%m2dbA-!CMv^j&^!*9_g6FRW6d8$S2tth(*Oo}NN7zAC@z;i=pvN3&f zPo9cn!;|Y+(|7FAMQnSR5lH!u(BzK;-+9(YS7;ae4|V*vDs2A+EQJmPGojbTEQlh} zZ)bO239j+tmb7ywkn+?ml^@ucxG4n0=Ti& zXtY@0IzgG#`pKYqF|Vnq?+R$=qresH4og^_GDR51p-R1Z5XY%_-DAbsibnCkg^?9qg7NbD+ zeHDF|PP?l<``hM)K&zeT`#L4hW00h>b|KHWC(m7<#N8=fX^DGm?A6-k+=P9OT^rHR zN3CNQ6BUhre+4kC`$tVIS@YsCTvC75;g`khT-d5`{?|u8?th^jxU%YJWMtIRvA|S1 zF>p{l!GkT{_uJFvZv)$-#$=ZPt(nX3polkA& z>3C80^WA=~k;x5CW@H%9vV>p%iz;R}fq7s_e8h7@U}f*peVx#43Un?iK$Of3SYJ&p&-vJ({^_p+S_z4rWw}n|Ovq?5rp&^BL(q@hg`L;5GTNb|&pW ze2ZP0b)5hG6!jC^ZXM;~J*wdJ(0VMf(v(SeIF2*F_6O4gp6Mm;De^8}qJ_VimDu&0 z`9P;3C3^r1O*WK_UG>a98jkYJ4p)Z^g9m%%XXhAX82#63>ZIIaU!7}xo(wi-m2-*h z8`$qIaG3p#s&pmfeb2ikvfq=Hjefr3RnF8)iQ@M6Fdp~zejh*f^kQaa1BrG$PwUG! zr20;%@9Jon_;WMZQgv&kU{6<Y-eDDHY~>*UDt2?es6ZjdcMiA1q=X_|rn%Z%O$#B=<2y*@!eqTJ)}`eU)3u`KL`>GYhqt$PM|AOzxOr{c z>z{V6Gs&JAqCtD~?AK*iox*Jj|KGfrM>_QlcS{nH#yfn@&(6+5&BO&KYG(D{WH6C; z|J{RXexc~-sT5b^I^CV0^zh6pU0p_0`yI7DE#HEs4kdia1)b;sbFc>tq@P_%C&CLYJO8HzHY`vmD+kb6ovUEYC32?>W#cgTMxI*!5 zM}93Fn=4QS5aiKp1b9+UuHHW#SAH+;qM*Zlu(Wpsv-0zYdU%Eo`hS16kGY{^rjZn3 z*b3BYV#kp%n$sM<_L|MGis{KD7g+u znX$K9zW*{m6Lrq!k|ORc>(J-22@m`J*U280um9~Awz8v@lO%OKu~NzGAKjGe+|DiW zD%l`<9QkyuNc-7&Epo_BAIc#8$qH(bLzGNp+XWnuH)8w6VDwL~wR+dz@Q4o%cXzM2 zr^8Ch%ULybR252U^vzBc4>Ma<&Kt?`&xuHg&IDegdv2OOH9ZY)@9XogYo#Z()|%3f z>cfrGP5C~4?Z|n|^U<&k4IhB3#FS@rOp+11qN457mkzXy_lSy$vSy~=2a9zi+NUx~ ztY>4T>35Df`Imka+= z{T&u!Uq~V0K_*EQSZc$qvgDp9^W<^3fqKfWN12zf4NROq`e=#vqTiX3NLD-AX7Xl> z`$LjyDt>e-@hdjIsrDVjv!J8WcS`ISY$(B-Vt|F`m3(854GvrB+by(>W9?VC4?fK9 zS9soI$Ge}Zw3L(FLchbsugD0T&kl2TWX~%oC`6M|vh>hwbo&wRUYUF>`mIfe8^nRJ9|`pjJKsrA?4@n{pe z*-2eeq5G`N^c7>gy_b!>kHIk;Xcz9*Y|%fB`*h;i9p6Z56~{6g z)BXqiv7uqgI`@l1oVxt4yWhhwpLp*GU5!n=4+i{z5E@-oRfWhe#h8;(1qEqiXw83; zF0!o2H3M_sFL)PLF*_;8?8cbDRl-dOri>ohI@8JgjtnEsQ{AfN6Y$R~8l{@*G@T$g zQxv~2co2_lJr1);s~W(*o$UqICm5=^aM_V6r-f3o?=hf1y44Jh!nD_rVAJgPGlvU3 z0s|SJy<4PB3>uTC(~Z`vzcMe7oNXvyB7kcxm@$_uMLRw%it}dT-b+AFOc!D?QeA?sYbW zEZnFU?!UacFvg^v6Z-DrJtHTa33hBYeoj||cJ$4KcZ_+wO3fMM@@Z!jgf{AQk}$p| zRsl#*!WBD0O-{~Kow@j&vel%K_ni5fvG(STpC zP#~*#c1<!=Lj!GdAHkcaZSdA5_ z(uE$FVjvY?W`<#<_D{t3LyK!`nVji!0O%)WFugUzZp0Ixoj$bklECy{e`Ho@Q|v{f z4DDM|u_wFKZn@|Pk+{*@*0yjSftXH8Q1cibpYB|NLueOzrrgh-!1(oEP!06dypY+E zy*%AR%Obi9QhdF<2FXz?s4wQRi&D{djgbEKCPMXL4SSO^Nq89V=JcCcIXN1Jdg5Ko z)yj53Z*7*ou8N{w4BY%mgz4+ac*yI#OS7=7e7?@b++gm;ljVY3p^1?{LLws1w6w0E z=sF{Ojq$311h+oGMRaA&Bx(AhA#R1`UqkTdtTOoA%*+mZAcBMWM(@I9^52x|>Fy@< z&UN2$U0Gy6~lsvFBO&nj00r~MgG4T;P8 z#$8bU>9JR@^VWJM1INy&v#jX8Sah1>#)h1u$WD%e|KKfuh|VjaEpLQ=ZmhH;N5=o@ z$E~2xIZ&YbMtsePCdgqkv@0kgqTT_&ms`~7V$fT4UoWt{DhbP_x5pYXEeOT=`LiLw z1BFfXE*fg$YM0@xwVqJIS2H_1JE6oeU!M5kOe!I@0b-(OUDEgZT7C;dwnkLbXSJ*7 zm4kHn?8$I%Z$Eo?_u0vu1QALuF6>j-8{yIjX| zS^8`@IIkZB11=EnFIQ3Sz1G_6@9ka6SM`w7dtK$^3a)9f`+%}@;&)ouQ=fa}>&ct> z4Kk~Ka{*#?r1&}P1JSXD@WAN|qXaQN#uKt|Cg0sPqSes3YqOi9@4|Ee0HB(*NNE%l zVcf6f`J0pgxQQ01xK0rM%$q)06^6fri7hKH$6O#ogi0tI6(8|6U3O0(;4Zd`l=Ok5 zvCV}+iux97?G?rrEZ8}0;C2rSMcM(&u6i{)WnR@MN!|sd#e#^42yff+n?s|>mTBQ3 zTtI0g&m+-XB%y%cUD)MZNtDb);$v?D#>n|=Vz%U;Y#@t$!?)>MhVr&wz~e9Ahv9Gr z)5)0ItPnBx-4m6|L!CUi9vRi!BnVUh=Z($UD5z;%nSaLzZ5tk@z$1Nh{l2J^H>cmV z!_v0%s*C5a9=3~gOfFr}-zkeZIef;^>N2p)n>8n%ogdsw$z{r1QEyfbR)vK!ATTKW zqGS{-3s1!sScqS`lNO;}!rEZCv`kl$lQkQ0f(CO4clTQ5GI9Qa{{GfQIfM-SwLg-U zWBn#LkCHh!>_NrQ?6VtWab5CuJK)O#^vMj9;Sq2Sbe%c`KuIY%cNfEr~b}X z9=#8^1mYxpDK~3;OM9&>`c=b#& zIUE{5TC^uZ!vZYp3KlN!PflG#coX?{&{T#8zg7l%wU)md`vnSj7~Zk`!9E>XgIYBS zg!})+x0#f28vfU!Rr*qJqD4t_^ifGdPR!``;H!IYwVn;O=DJAx`?$P#~=)dcQjW__45(8s88Sd z;akms<-?t1c)xw>WOUtwq!KJ;={>T}IUzTm!4JquJ3%^0PI0d;`6rQ*OZQ&#GxTr5 z=cU&WjgYgCRC?7cBOU?QD&=;e{g`w>WDxFJwrw3q)ZT0AP;HO|hWwgi@B(KzT z0F;=$-4}26Cekc!f%pXeN!Bx#w#QirE)0vQY*?t?sLIXBsZt%*L)AzR_V^XuE%9ou zb3TcVe3#*fQ~uNPDEJb%9gXPxR4MU`5Br1se*DC5Q*VO|=*>iunqC`1d^j&x8V57q zrM6aPzVn1v_9qEz5*8@cbHiga+Du>6qW_D$QaHlHgJ{E^M3bl3DDU0cIWhn5*{^4irSw7~a6Ak4&d_e*FannZJrS4iI9E2&6gp;4AK$Y=TGdFvw%0Z#d{CB#FAF3M@qvsg% zqlztzl-F9(mkX@%F9tp8m~SOM*jF2*n^xvFpOqVP)nYxu`OUxK896wT`KPP7NgwC9 zaGFJ*FZS;w$>bY5m{74XGG{SdvI{bbplQF*0geDR%=pIHRwrV0R<8Bm%Jbaca%r8k zeKl97r>54Y&WiJrujVtot=M=u%agzN`Nd3lCbPyC1d1D?^SK9QwwINCRc0LFZTD;y z6@aEOCr8nTpIHro?CHMYkiT%pxc(dn-SL@gX$=D0?f1yn7X5ZNXMei3_%26$kr!6w ztR+oSSjJW-30P*$*1W!)Qj-h7Mo;{lt0xT_Qe+>Jg;;gSubbYey)a&ru>LAAa{&-% z6WA+uve-vFK~CJ{N%S>t_fYct#gBSDK`DR$ehy;$#ZDFYOVv5*C*qa2_qL6B-w0iy zx?hp7xMeu@(DEKt0300U+}vDdu3T|H-4QYwfM4*3Ul{X`jcCN}ncXtL^F63m-gTXi zJ}89^tA1`7J||@;?1*Dd`fFe8S$FNVuY|vuxjjBwrhH5qb9hIFdEAeg8xDS)iR_w4 zG`lg2(`}JBuK%pQ{^PbUR4c%s#5lK4xx+;4Ev~Kpx~&tu!KIYzl79)UhjCYrsJGe< za^i%mj;F4XTa%!Mq#7HOMt2m7sh-1nT$OG!-Yqr&{XXt`6hU zjEhu9lAeIK3N*5?u;^}rwN{c0qomD-)^43csoZnIO%#Lde_kc!~*qYAHAe*tFv;|Zr5k?b`tlWv z=xHmhk2jpXbV8e(tlOF_rf8=v$V2UuUfq74B9j_zQ*N?#)??~707aweMO>HLUYAjb zX(1k>Ek`e)mj?A{BRvQ$Xgf;%5-KSzaLIbs!~D_R#Li)s*2?L7gi7NL?>NZZai;wk z9jC>E?^z`XcO%v>NxW>53SHLygm81C^ak3SRNW*s$DP}f-Wx_zhaqb&T42n0VOj%O zRAM)pUmi!%yM?bj2NY1IAlUoLF~>roh%l08(2w=wV>j5=2x@{Ea|pDjh|? zfLT~*?~cKWXY!A1@DHflqcFM*%WNV${YQUDcPPyR6+K(;S@?LON$vtOb_$aj6tWop z@XXbuMa>e{xzbvDhA#lRlw8m582$9*Cl&`yVK6~I8C=G9yNI2UzCJz;A!Bc+ILM8n zzL&!ricKdICcV}!4au{r>hh>g0oCmX+^C+S4=g{KGKdK1$bP=|fJ(#6tY>iT*({LJ z!?O%ikhxoqn6n;cN4G$=rG<(UvVoe7-O`XT=Pz^ zc3edDhMyiW4ikE{_gYMz*ca4wSe5msy0XOsEgd}K$s($z8}}LpRsrrhN3-%qKW>=x zU8?mhAzt{i#{!aHK6`CzpW?p%qixrZ8VdNAkR}I<$CBKPUDyMT@0!kW+_z;w?Mm3* z(f$Sgq_=To%Cl_V`Z-`PCGovl#DDy}^V-5}jGMDOYJH&*XORp7d})4pcXEOL$VKbd z^e!|h%PZ%(yxik55e-dECW7J_Qfml<^*~cC8&>aRN>nuUhv71}X5X>?0npyp4?63+CB74FcJ5pwWpD*#0}0=} z-F#yUx(e3!q-XRN=86T*6y_H)uLyeAq0{^ex|fGvdOd17M^9V)H0c$f*UBA16T~EY(uyRZe{1&G!(cMKHv3xA0Kr6*4%zEF)zXh zn&CeX=y@@(YvbSaC~Oe{<28bL<)5@)1Rw9^A?(pj%RF{prHo=vXR}a?+f9D-V=@U~ z)BVHRj_-eOHt@2yP+WRv9h&wQH;-@YEaF0hKY|MWsoo1&2ZPhYNJ7egv4CXq^98lv zEE#gluT9C#omMEV)Bl9O#xMFr(8ktw&M32^F^4$5u$EW^$4>DtQ*(me*c05rE~G;E zI-28@Q@`S>=Lmt31%>Auznxaw?%m=rjt7J|57<|+Sw@N?>rn%>%O~dfNW_A8Ty(o1 z)W*U>MVDG_HOqWt5T|P$2Unk>EsJaK3G;Tb#aDBq}`XP*|cYj#j zUTvZXS9h`Mv`qg=G_+tY>zfaDj(TAnD#P*^U)Yosaoo0S#@w#E4AFB!{3$I^?})xU0$`3UXN;O#jQFYI5AjPAW312~Cx|i0TuJ zro<^+`PWJnq~10_Lqyk1NxNh)pWXF>O$8hVx0;vf0B;%t_F695{-1}NQFlO) zjUYCLi>O^#ZY(V;J26t^^ckr!JlEaUR(Kj^4+=4Srtx^f@MvOScoWi>GN^uuS!G`Te$glQBtSXLIPuJ6=gh&60-z zKz%0VJ2#BFTR@8%+>%43osc_qtfL_k^^6i&@-4Q`L&@$-U*BZNmy2zc=Zupyyc4H} zQyjJL#+tJ<(=P~*QBTH}yR50?FdRsgTDO^N%Sl(5_jii;O!wkW4oAE`p$3CudQ=e0 zL6pqJn8C4-AsR7EtM27=@~hjFTr>{99txrR=WLjyJ9+x0X`Zfq`I`&C6PV0S+MKJB z^~*romZXkpQb^b>`@mD# z%XcP!)CTxN@33kIjcqc0^b8MDlbNj?4j z0hvuqce^-;q(Ru|vVZa#p~oh$s9`K5a-G*0J)S>ifk}IgIXjlJHa&e69i+r`KKv{T zR{hw^sE)VS2a8k_f4_WA6jR>dlh#_PUVgd)?>J)K$0JYgdcEFs1!itx(ejka89qWh z7e>8l=LV+poCSm$TGr!nqQ3ZI{@h#dwkGGkKONn?ND(0Zii?f6VTv9 zaUz=kR5$RpYCduF$yro0afuvFOIV*9N1O8dX(!&k4La@afY$>~x!2(Evxz-vH z6wt>Fl(?E9JlwZm!rvY$n6A;wZW>Wu_K$9WA_psOGqQjrR!&1h<7T@S5C3{P^)Jm7 zVA{oj?XGcrQ{X)NPrb<>B3_BJ&>>%03IFdBYi_x@?T{1I+cNT6zV#GqQ@*3_@Va<@ zm+@|e{UpN8-L9n#3NsdGJHz<+Khw?y!J#Q9uW?-j0*j)3AJ+{Jd?D@{Dcik?Af6rs zZM>_&yga+-h6sK;QMA>nv+>T|=WlVe+VQDOJZ_q~s||;n)ZFT3s_sz`5wL!9`}A96 z3G{ml?PU~GC0f8sgfh2$ch~*a-C1Wi5bn08Jjj=oj?rQm5_upIFaq@Z^uWLXGnah7 zM9I{H8T&8uNTk-{cd(-3y+uw2)o}M*{)WT@j{PIbL)8qGjTV5(dXuuH{yWRNg{(OO z@NDW#c0NPd=`ZT6=|?2ibL|6)j05`JJU8fR^!#l|Y*=YF>k#Xu73Pfmd+`GDz?ChJ zT@QZ#u@vij>HFf^?=)jm4)b z)yX^QzKL_^>JT1Oy2SH3d;A5aUG{fOCQk7I#1#x)(iJ>!n4miQH7HY){7T}uDDLI^ zAH=W8bIu*YzaZzM3qZ?qwMyj4uSn&&*MU75r(S5Qq4m`m`bnS`(0h@4gQ33>`KIT5D^)son4(E%WT&!k=zaJc*%2Y^4=0jp;z zR+OI{Brxey11t_rT4dV-)QV=^E&eqGiGu4IZA6YvW%fY7<-%D!3+SjhUFyQDSJTt7 z(L|BDudml+9A2LbGIX@;4hoVWzOaMV+$wycJ9fZQ;c2UUjJp-l|Hj^Tvr;=$!@Upi zqv|$aT%#-IVV|ur)H61i#0vY6XI@&TNQ`ZI(D!^S&;@^qj?_eIt@h=6f)`bOf9OnR zcBF(tB~EMWqD4ZDf9C;iuH9ME!9W_(WsRtNc|rWuHFNt{HTp9BiOA|#qK>5h74`@z za%kwK41$RdvNX-+^*=rZ_-P5wvjYvRE48~r%%HU!igo1@cLxJT8gDhcqV{AFr7I5Y zh!?t10MR?r`;I4QDfYg~F8^c5*2^*-96VLu5xEedFvVwAUTSq3V`z26v4D&D2O46N zBfm1vj%~gB_%EuNU_iZdknB0LozE|+=5T4q7m%4r`V7uFa>$PhR z2V>);6|zjkrd%Y5I(YZHBA4&*g*%=fks9^q7UHz~ffjezq*NHQsk3rTGWxl4QA+vVl2=N{ z_%D-|0DQI`K*2b`rUe8$uLh>ut08840<}MaXOrH}A^8UhgGkKf8Xlnx`;p9il-D`_ zKZk}*Q$*KoQa)xH%qIPN0aeF~n7u9h?OZfE^*gN9)LAuWV;@nQHW<6U>wh2@FfTt& zf!%2;S`w{#Ked$qEzG9iLIJ-i;o^XSF6X#O>f?}K&#qt|3_?dBpxGg*OTy{8*uDB; zxf@aJii=_=TAlCrFOaU;q|H|Mq_evKPY!G9{pkX%(9e1K$LAdKxJb4j0e8qR6yDVH zvp|~img{n8OYG#~r^oBr%E;d&%n=FDhk0vC`%$)=ILOiZKjl<=ZjwiJf3w<80j)$m z|CSRbFqoP5yGm6_rjyt?OZ$v5Hu(S5NON?M%5`Df!woln~*_*j`X2ysvVbq^Eu>Fs=u z+r3XGjd^&&Cqck$w|VOT5vmL-)J~l&c@IkGH%3(XN7RqD_a4C8OlQLNOwN$;YK?;T{IA%&1?D#;eQ5CTMt1 zarr0bdqteEO79$4dDI)M$*!G6&Ne=_>z5f%Ng(VvS^8>Z|9-~SBqSBtVAVu4Xf^+( zdvhq^uCPyMtN3JmXX{_B}{quh9RxQiA~?SVLDaqXm>7E_e$Gk0f{FZH6%$C!J=VsIIAltHipUH z!b+Qe(NwqV^LR9nN7|)V`p9UfF6J6|-`pVVr}svNM;a45kYLr$O4t7uh&wccpejtY zt>5&Q_5OO!tvk#dS`>)nA0zdG_X=cXXZvd$tSVjk^4icok#qCGF8@NGeP-F6#=Eqa zzAzoVkJxk~Px_ycS5QqNb~~lsIY1t)233{etg1XCByJBLydt<6@%g0|;A@#DiIFZO zrAy;*ps0>gW*o&@048>JD!AB%*eW=)YJP!3`FEdK9fuu&>JZ-Sbwd3xr`P{K%5z-4 zeg|k1|CS2~d0t^lPA-$>3b7S;N_`Nm{1HPyr&Z9BEmCMl9()X*CIfgjvuKc=Z*Ce% z_degl(~j11B{Fw^Zr z7$s5jC;|SU2xIAnKxBe7oLEN3q48gq#V^r)#^tb>3v`TJe&?y1c>sgtPwBf2W!BTUk_D_GrCIE_!K;)b? z{AaJ|)RM9O=HWynaYx0%CXv=SWtYqD?)jLbqYs!y8K8t#uC$C-4$3TDNf7QgogK;2 z>OWbo-4>z9_|SC3GEvpN|4lq2_=r!imZ-0{w_T1K>xRtZvd~M}=XnDzlBKmT+u1Sm zC@p&F_?=g;56~tMyJxren-hCi2X`&kl#X{7{_cZmOY8p= zBK&eSY)$?XaVSB97_<+-ECK!8=*0FhkiyG>UE49Cup23$6X;FEq~XGrVw)hMw~@BHp=`kwI_Er*?}oQ zliPPpVUERYc*Sx29XEHJzVr8-V`<)C@H{!IIsjJOHU*xbHisIl>LN=UIMm&rPIxNM z20;^vj4o1UYbBp7Ja3(pVgw~km`OcKO{!lS1Cq+U{B!W46w8XqlhCa#tfSvO^c z=a6y}yir>ECU+H`d@-{;``eXqO>c^tN||E`^s4Qlf?UYOo`a}cm-=}|uMgXvT+!C& zlSA1zMu=0myuvqQ18Pi-Aow1Y4cI51@AMu4(v~ozNpe4?3l*4KgB$7YR=qH3p^tO* z@L+iZJ`c*!fb|?)Dn62+v8;aXQ`WjH4q=}uhtZkr5PpoQeZ|*W^=~64(-CO_e{D2! zgpp<{gUKJs>6nw_PAKs1U7GCRSAcdg; zEXKkc4vIRH>cZW$zL?{-{obH!RjnJllxm#>uKxFKL1B>9ZB+X6*49>rim$kzU;3g! zG=VY~yv8c&w@r8GNaWkbTN^Y{gUf1>1B@^AWSE9_s>h`b741wlS4bqy)5atpvD5p+ z8+u`+tacO;hCwZ2yGN+ccN&fwByNqUZzSLd#((Pw8KJ(Zl`yYhysVwKK<4 ze{=sy+!d&1)t8Mamw3`RF0zJ01DvPI(=HnB6F|}j^9Z&Io3LR$A7Khd!M9PEvhq*M z;R5axf=`mN0|hX(-ylGqYnAa1B5hzDc^oku(0!kY>K@}onSXSsp!GCS9OJ2?RfhSd zgxPmWE5SCSg~a>Z;{)Cl;qkT%CVs-2$z)Stk7apGr0Xv~S!dF!;InxK#A)5C879!I zRiE4#$;PmdvNi{d8rPd{_+v1Q+tuC&S0 z0g#OrpRReH2BKe7{P(cvS1sx^jJ{L}z=krY6Bb3lT-3Zisz|CxkVctOc|fpWRffkL(i=JownIfcXDUKL3B)>S!f=AFb! zQgx4qhsw};pRR-j4gtqptdhawz2GaoTYCiJW(ZxAiFn>n5Xp|EzrPCZ3YKM?qFOaa5J;Qg==z4+P7bi^boVfr~DJAqne_Y^G+-+ z7nUenikTGdMz+zuZ$BvsE+1p|lk8~+hwvUb?fB-5yug8Cmq@t9>%cJfr7(w++!g!5 zPMTZ=nE|$Ur(?yRUHx#VUi!!B)HAMEe8nfCf%TBJryUiK2l#gTIa^o>(f9gqX|U72f5B?M`A)Vv)w&%4~7~Q zEsjDo1DwknG?w(P06L+i_Vid#RB{qrnpM@FUsx7$f-+n?z(WkOE>Hs^Lf}PXKh@*E z@@vDHUiP^VNH%rD+SWD!cq(Y7vuFe*)omo3|0Zk_(up99d>I5+iKeSy#`KWTH3$_Y z!!)5*sABbpx(0GZc|0*)#uektz7#TpS=D;(tzKMEHl>jZ6&{PSbVwyg?fO`v7+?uX zrwrGltg8A6vB{d#`EHgEDp%{ZTE^9c4Z3MnD~!Q1ke>CqY~J+;({X{#=H3y+KEG#W z>Qnx5!9Uq8w&;HJE7#keL2j2yN>_2jO%D&+8<`VX&D3WXGx1L>pdjbnf1|%7TO|*u zyymujhQKh|_VQ(pjl1e>Ecw5tB5>XP{Z;+tv}{03cy*oSI1VI?D3n$UP|BX~YTW!N z2IPr$SxfHA%b!3jkJF%#_azr6(lOJBP?fCqcgJkHy7Itx?_AE+(ErudiMg zC~Fi8ypc=!d`=}+aLUgQeiwFn>Y(_+RsSvqOhNW@|E{)$+tw-}1CtA=e^~HIb?Y1# z$*n1$XA5?ZxLmt1Rlb4i9^Q(|QWr^S#PRVs1w~f@!Kb!o^JL??SssLEqAB2OMLr;NS_OKo$(YAAV z7+usp5{MX^2LD7}LMNM6hyu|Z-h%l-|1rStvWQtsC{Nd%CzhF`+Ei6;cn1tH4jjU1 zkUxV9ZXja=N?xOX_9Chxg;E{)X6slR+6^F9zmhnSibv6gXa-HM+&{-0Cw2j)mI+WJ zY6=rArl0{y@J_$op`-RRa4E2r_hkDj8XP+kTrF;HqXLALSAnq@?Ps=CbbqdXMuVR%lzW&Vr8g)%4C>i9m#6Ssjv>-O6iTp*9cIvUcX7==;#Ji~F!NGBi zs`lc?BgQ%F#$5~ts8e7$u>Q+owLCI_*^=IVOP#$_!B_VS&9j7LNEa0TLQaQwJ8b>q zoWV~z!Q5<_j8x#XQXBKpTQp0g97%bkg-T3a!^;5ayNhh-z`mSnt-)sz z0L%t6|yL5XO`KxwpF-7k+ab($$bOo0%dp+A_0#_JnUzT6(&q3vdsX z73WfD?0R!8yEQZU^Rd{EtST?@<*PB4tB!8Mpl%rv2LSVUE_CQL{7Z}lfM2w}mx}r7 zoD2e+9x?O=Du3|_{{@vT(k2>@U@5Kf0V!&=)7!~;3V%1x!>Sp$pNJ2!|f#7D)o8B`^DM;)*hqYzT}5&`6$uyeGHJ%1->vA zV1B$!Uds&_<#k9hX7oe*^K^0GFT*Rinlt5|Yc5or6rU3;X9=QyLUq#oI5jyr6gXnH z;x6}rlE5)uy}GzaC3>u+wfY*mkk^!v1Cj&84qCMF@M&E_Gw6%oQ1Slzd&_Pw7Nc}R7=>(_PlIA zKU8MzsgMknE^F~btYn(DL{5ctz(q9D?{z_Wo29zFUxIzFnf|!6^$e%;^+yX! z(5U-d0_r%wjkB7mQPBDx@;A4bR#{=jzXC*_4NOha6~D^7iVNj&_EoS?06|Z?J5d*P zy$HxwyaTEd-5!7EgL>Sc&BR}?+);3hkQ2MvsF0F|MEf{aAjE~|961_#folQ-Va3U0 z3CrAz^I^b|!v>ngxO;+F4xye1plP5gt^J)7)rdloB)2y+OgVXZvb?m@8aYYLE6*=} zybD+F7kM&+$nMfhTRFLUMR~Q}e}Un9)kL9FXMkjMS*VZ^x_F5`b>cU#@X%QgnKCyT zbB%6%n9E|cyS+f4X1Ik9Yv30e8aiA%lixU*)>B6P(|YJb60i@`%nT zOvqPKq4EMaQgD`rW9j~-YDZ%*v!+Y4IW2Fbu22f@HcRx8<=CQ5i#bhycn`AxZUz09-u>f<05II{qZM>$Yhn94XL1+fk}$`jy8@gV8Z zqE;2KPFN7{bxU07#X~QE9we#FI}e82&Hs`Pgl4GZBKl*N)2%_ViPp5%YFo^8iS@gh zTZ%?4CyEwHp1944SPaxn!FieueLm@@$`%iXAsTf_60sGBB<;5{(!w-VC)aw$%f2s_ zT?e%)rXTyI z>g!_A%L>X{q^H5u7#o=Lh)KWsesR1Ot`5>dskbCjU|Q$U;nJ=%mY(sR^rN$+(NDQi z4`I3l<)}#Oz{2u6XKGK^$5?W{24wmxrq!g$^Jr0De~f21%=sFyQ!eJCEiJ=Ae0`d@OOT3Mu8 z50X0lfe!%VmaG(I+Qy9>c5(fHNKu2m%3Y(ok`?xN`~rx=0W7HAdk}8&PuE*b(5N0m zdc)@R$}1`Gxi95OnUonbtIxUY&z3mivhC;2uFiTnZOSV!z4rTJ4MLEG9vsQw5vVdM zo5A$j^hAkmxiP5hw6eSiZ*D?|dHJbc@6q`e0(zNF%O=}Am5#aP`l?d?C!dsVsbI0( zulw2UTVU)9KkRe`C@Vg;rHs~%8s8FF>Rw<27-WYM$u!r{_Ix#ey~dv2-qSF>(eZB* z;%;e61{YxSQz5OnRC)EBTUs)9J%-+^8in#`&a>ZzW46;ix$v0U3Ltu02Kj!XHI)+3 z-dGTPkQNwN#bltYL1{T-~Ued_iD9O{d;%0jt!_oedNSlFZD+0~LEU2v;d zWl=?9`Obb{wT0>{s>UJhoF4&buE3*{`Qqrz<^fASdOfWD?}9e@dxe`#(W^XsX462_4h^pxQ=@e@oH(EMtN;gfCX@n;T+-A^qomn)fv8wx}9 zkIg+n@;&moskYY7#)4IFp~}eWN?Z1GeNYS^IqzrlE*+heoXk^jv@ATVb0IyMid3z$ zZUCUY$F)TpIy*b99u%8(%!vzGmN+ER`S-FwH+4yMoj zqOa7&!8NiUg?CX3yH�eaz^<{Z#B+z9I=as&SfkIE5>gi*pGY@4^hfJ}waR=Vp}m zJuEo=(!kYO=ayX5Ni5slw6!pR&U!hSr-rM}6x&YjR=<^^oU$c>#2%6~u4L3lHk23H z_SoHvd$7b&IC6et(MW~ysYJobKe(F()!p1^X$#n*anzFyuBgvG`tG#5cY%r?iYGYg zfy~pSklo}mDBd+lCbE$j$T_ZI&=PqoB{i4YSZRF*#ED`VzIK6}UN1po0XDcrNN(_2wYy?Jo8t@V12jJn}H#p@3Nb$|D;Ld7#awrSbp+=WCxqV3rIEsYO z-~A-|f%VZ^81TbejQz<&YOl-zEBxIB#}H-O&c-s?5n?NyovNL`(0a4{!}K-FxWfAp zOVVZ*%XH=GHn*;sw|_tDp|hoN?tz?~x4sNdSwklubXB_omA!84$swWt4RdyWS&(67 zE4lm;$d<@~VlvE<^zcSKHtXJcu; zGYBrK>XA16x6=~d6uX}Wq4o(O|`1Ji|5@3uui@sXK*-1>n1COZJnO^Q#NXj@9A z8Byi3A6YQ#W}b)1k(c*9q`4byTYwqy77XTrQ`xSfQ-JOVkc)3jO-&Uj^xo9v)FP3` zR>tSak-d&&moS^n&71+<;Ns(JkJhcLIhG|ZT|lD3fxs}$0hIYsv+YH2LMwBl(@#?= zpH|XKoQ)Sw8@A9%R|$=|($Ze)^zDym(xYTV_w+h>(M3&Z2e zl`~1k+NFP4;u(iNBj1pCpZ0Cm`t3^q*>=)Q5A6(ogUdcQhp)9PLZ%M4-nwxcrxnM7 z8(>K<(W*zWrwzbRI%zji=(RC$?T43Lbk@GLpx$f>0_=|*n;p|6yn%1KM1?yO`pr!; z@i(eptzkH+hzW!Qr?9DY$!;5E=Ip@heRRv=gt)^(iProsY?C|V(BL^034GwLrSu8c zL48&+BiY!;GIAgBNNWxg*^bf|O-Zi=okAoBKvY^EFxu^P$k|GvpB-PR zM~akInJ@;2SJ7hZcfaGz9B)vZLAZQgk7O{sl(#2z;z9rnWd?4l9u_eZ%Ba|^-PRgz1#TUY}`efLWa z6PB^kBJ{=CA&lDhXKIpe!m&FT{i25IJ^KE`h(>R*}U;ZA|}Twx?8p16B?ByfLgrcI1e1a+ts$gDb3(4?SUu_ z1!4-3v)O?i5EfEZqXM-2rli&Wf@|4}Gwg2r^5`M{t#dPuD+(2l} zLPniG+C3|pvG}4FzoHo@?%JObHK5aNUuYkjDXHGg=2y7taAFWE4uG!1F)rCs)3$*w z@DZdoyM^SOX+nNk66(@Oxx)(>ND%~0i=L&Jf^;-ILN)u$Z&}=wRB;acr0+Cq2kJ8{ z2F3fz6vVtubFI(&?}d+yKnJg`;I@F7*M-c43-7@ncvKc4eaif*0_2n;0qVHJ%k4rU z-U+xDAvP6#iT!Rni2o&l@Gle;EikUq>a!^n-^zo%7Vhf1XXr%#C$ngQ`~K4v0oAvr zrYmx~MUXR90QLAJ!Y-`J2XLiCS__2EzINdF5(?K{ZWF2`-jZ>HpvOCWHayO(-apsQ)oG}z~e`I8Q6Tz7eY zaNxh!aNm6zfBT99Xf*Xp0~cy{!yNd~MH8v-PR%GYX`XnZMG|!ei>%16q)JL{(3G)? z65m`9jNo&xLNx!i&(XerTpuG!<(p7CrALL9s>BA$s zK#Is3T!3`r{=h(5$v;DCpX=@b=Qwwwon@Zaj#x0a6A%ac!wc8>;uyOLdC7k)n=|w< z^!o2C@ikeCJCHTt4TGr4(~bP*P5Be4*m7qj}df_J_6r)(LsTkhNy5V8>CJ6`2j&ZC;_S(AZ129)Z-^1 zJ!z947eWm#qzO)?6#MM9`11j|8gxfbVzSXVEuTNqUhc(%7ZMYsHG=MV3?*n5^-@nP zLPC42UQ0~@s~OhkDv;vIw!=XJ8)a1iDo^#t!~?*16%w%ntN~CgS_;yPIYB+hjc~h0 z?~frIDnX?8DFL|O%-XtqNDHeN=Y6fPg~zYqIxtUx^)|F*|FnY2chGLFzing4x$vcA z?2DB4mlw(hV*~P&nx8fts6X&gjy^97Vm2}ZCS3cD3_%xKix0`wYH{RkAUECAI~v40 z*F_&XA`SI8c?dW{A9;>JaGX7h;{=@}wyybbvI44)(ihT`)=EyoTG3r{Ul_UBqQ9t! zDNTE?0}B#IB?#NuajiPoZ073Z%&wHFTq12E0(qPng4=No)xY5J3?(xvOcWa`h&|ix z>vsskCrbkH^?FQ1(t(u*UIe-`K4@p6Q%icE7>nA`U2ZjxbqlS-!MB;eFkH(G>Ha5~ zT2G(u?V{=eY11CEbWhaq9$HWokb`jt61 z?-E0hkyM9BjGbLbRe(-S;|zDlLG#hw-|Pq`z%t4b>JwjpB52KXjju>_2EEa4T9!&^ z7csZEmU|356*&ZE9sJr(Yo`nNcEs<7rQYo0bihtyIV;pacCwSq6T+xv8FX^d2Shjz zTPX`25LKZ15E6jr+_jgS7r=>ix4vCqXQN(BBgcs!jvgg{%=>s%Ly?!sv>(Z(;Dqtjzt?zCs1=#>*hBYCx{CW5f_5JK zvFl@BItI=vd58Czd&er6?mj7@Sc3VSheoSfRQlC3W;ERtCq6$rFjeAl5|e!;P@w@~ z70Rl+J8lQq=7A@81259(D_Vj*9q*)6@4mW`)fJxRtY^yQN>{Y!iRt;PYp zgRYFb1%$Bw_fHot(xk;3r)u`KjKq$ly7k#GAKVjxbvqjaX+u2vxowE$$evDcfYMc8 z!WW`dNJEf0t`5uj^SX+SsH2yT57{CH7#|(1fviY8_WT@?JwS+#2mt1dG~d8C24>bK zNjqSZK{rRTlqauAG&9Y;)1_9_q*?Vj@M&n{3l&ceiW5N;qv2$Kj+h4`kB1!p@9rpm zGjOlTgW~9rD;v?5qplXaWcT=JyYPa{%ihIl=U-C)NDU4mgTPY8r0w*mGZJ#_VN6*%NkN!eO9MFtGQ_(^`d z%lV7%zEAJs}LCtI?=c{Q(9{u%a{Aaj9*?|TZ{=QQ0_k`uI zO;-G*Xyql9;rzhx1*tHi-gZ35V^6UOAB?+DVYaIw2H)}6S98OSU7P2zMZVvQb%m1# zR%%!>&|-dO7x@o*=ono7YceTve8;&;k@EIfT{C_1O0xwip5hwNV z#Cx+UO1tMQ(43Y1%ApU+z^2l{S!^L_Fi) z(oM)j0e4Lg9DOn6GRJB5cjqz6Wbo?XW(Wef`-NRqGnm3VXoLPjge}NI+*AHneK1sl zxBtuh27J?Fcz*+-q4ZxX+Ph5bkr%IMyG=)>Z15&j2kq6iFAiVcA6nl3EOSsrNub}d zi$e8GFy3p#%h~rs&;zRy#Fz0Mp^(8VPBb$)^X_AvftP7;Z7-e1vYa?Su&7^8JDZsk z(yK76PsaBZ2t8EB9IdYJ)DvYF+?BT24LnG7$8)HvbsIs_Kl9>^TA}Xx=1om>-=mF1+Mc!rkb0@QlTZ&F?i&mZqop(QewY^nX+wUb&VbO@%nmf zs<0^;>__vajpKaGgs`Dc-vj1{9*b^YoDu72H)}&x9Y&*#6NnmGW^#`aQzfoeF$xvS z89ia%lALX{hrXfES@`(29}U?HQK8{(@2B-dbAacSvisPMp!fy>4>0yZv;FS!z+;7^ zoq()oJveSOh9G5OPgY@8tFRX*ys|tc`}i&NK2KgtCT_)-eA7pBYxwZiF!@qoc9j9& zwl$e$Q($DpQ5%fAwLTYKPG!zl2olEzGXvGR{eh91gwz=Hs3ool)J!kJ?ysf`QhH`z z1&|xlb;%-=m-WPHARY}jMz(cn$gK)Xr8O(d&$XMl(N`EZ?RS;mQ(NPU6|dwqff0C6 z=5ny+#N+CzMP9=n31g6kx2T8wq$F>46^HiNI#@R9HMd}+328PE@bD1S;ffRb`)YK+ z#bc%gIxhPvP-%DJ28pEMAafCTNzfW-_<9qLT^lEV8Z<#Bep@QdeH;BR4SakpEtw(D z26*`oK5(jhAw5p4&e_>w;x#ZX&%D2ozJSzTs|FhG^Caxi<5htI*U~toEN$%6TZ58! z<>?vnSpzW^zzjb$&wH2SY~nbijWT|r$(0zG*jq#)m7pZ>odH!o6{;Pl-{AtD6&?+M z?oaq4Lasj8RUvLhl5J}W_Bl3o>hznwmMX;4?Hko|!n?9~n=0rER{O^KF7>Vi!4H+< zeSKs855+#}Ak?k z$1~22=-V@wr)^hTxJD7GoumxOr%rgt(@<>PGHhlUD|a0K1|c|S#4qi3LI;&ypvClZ znIO*rgCMVFpfdLIn4PoZzYDYPs+@NN3Bc{o01rIy9(6f6PvoWw>9yVc0unKQ2a4fE z7E7=odsfCHi`KyYeO6)MeKGnrokpJr92FgTA{K7%-Xw?KegBITK0ny_!N`!B4QM7P4b0ip z@zd82aB*h?$NzN)PbT1>cF2%7bsCT}IZ&4QfOLi6v4DC;P@kE10}y~HnSw_Sli8A= zGV%Mh_Y?;6ITF*RcG{WHog2)?sgb_|hIhaiGW7I-N&{rU)Vu2d+v3&zf+&6beP=cF zVNy|JnOqcP`Q~vgp`0^D&q%er0w4NmHXKx1L#fCV9R2<$jOLB;Gg2W%n-V;6_RgPtrn8#;Wb{n@u z|3l7v?SF_%s9F^T^U5y-T`@Somj;CjaAb}P$2J6?$lfVH0r!D*2ib!mx0=fpJ-dQ* zpcOxX1<@I#E8xb(aDL>}#0q5yPseT%i^r8yBg3plWG%+D%)y6J_r(zW%fko%y2bft zLZ9b!-8qT-+jGJGcJGLcCXhpA0Pv0hjWc|4;9FnH-G!DFMP08PJ+QBx3Gx2@Ufl3F zK9F>-%4WBw$mm>!Fp&eh#6QAMQ#$b>deI}cEsL9s`M<6$2JiW~pZ`PlU;rTd;s0ZvYW0=Sl7cyVNaivI7!eZO#M&$Q*OtC`4oxa`EZ{++4PlZ74 zitv4k$?J{;TeiThHQF4NZ~swFD&%EV=2^w8FNwf)*3UJY=1;7ayOn?cB$Q`ZHXd_p{ z3&LPhHk3`;y*DH!uIiM96uxDLAO|YLqTBJ2pp}d67*3Vbq)n%GcO);xfu>Hn zAo%3XTM)@;!c}Tw1Nv%YfBoB4R3H01gtqvO+WA|?Kg1G@fC2J9G7^*LG z$B(u1^lH~t>~n)aE?Ip8-?W0_>=IAU@LP_)|4`X#njTLVzx?)}h&?GLY^;W-qF{%> zpeS8h>$OOn9FgF}{*J)H`%A?XZR8X-w%o`vG#;B}2@=t3%XnNFIOsH1)1X{$uD4l? zIMcC+6H35lwrKaR`!8TFuRB&ZkbgDvSG>42HFwy@`BYb=>j0YdGoC%d4&zm5ARUf@ ze*(BmVM7hCCs|CbR0E6;zIBSC6OCw63@&_Ax*OVz$Af^9;0-@%YGO- zSHYmniSO%E;X;ymc{3zqO#*(xQCDi+V#G!CAG#G&GheM)&$ZGVEwCC zz_5)bRkZ5+DK@vc(0+&eg6uAVHfvP1A>+j_9iaX6mEGa92sRPx@kW!IIk+Tp&1#!x zHjsuKmf0<{2yB+k!dQc3+=}t!fc>&MzoWLg%S#&O+a5k;FF?8dR%58}8-ascz>8Uf zhI>-r8$jqdn<(akeh~=j!AX5n4w0VdzJ9hNBW5Wn6q=H+&F*VF5a>0P*EpBlC-ioW zbNEGX)~ku^l5?1ZM-W8|g}$P4Eu)hxi?36$-R}J-Gky(Nwuo6QG}OkO;AMr0ILH{K z)aE~&wuw`ocxh9GW;)Xe*wz=y*8ftxJGcI*(Rkjp%diB4qy#p_G(gg%##2<5f5~~z z!zEaFsbj|kiGdhq{6kXJWWNb@!GQeCdriJ8xR2d1nuLeLdQ^E4$zkPIZmV~7?1y}6 zAtG=yoi7X-p9Lk`a=9*@c+zhet~n0ZobVOzeiUaq0R6?zK0o`zE?qo7`4^VT-)wy= zqyuXq^2O-HAc+aPZ+XmfJsg|BLw!a0!~Nk-KSh^yjRsyHGn&l5CS2}daB*#LrofsV z(vk7_*F_ffYZA}srm=9L#wQN`!d&LQy>inuaRJRhyCfi)F8vYmu2sza21nMAaV9Wi zPkFRx$zU9vT>4XsEx#Gh=5*VgNujE#zF)g-ly+n@G-Lb~AhB*Cme+{nl{NByP29ah( zypD_lTmE%sv-|g1D)i*m2pp$aH4ujrSeO|Yn~aOOf+)Q0^)HHD7tt5M74A}>EpD;a z=IXDLUx10=Q%otdv+m%_Uv=xN2v}co@C$2CZqrH1&hpI2VIO{ZrXX{9c!|u%vJaV9^s;9f*hD+(C*_31;YK!Wok|;OC9Tb~6PlS_ zl7uI=FG(tyy-&@SY=*iO9d2fkEEG3p&mNRENq49%trSCF(heM&LVY|v^;KxC$5LO+ zWubvw;Gwfo^`FzE=RI^P#y9M-M<<(oY67?+TwL9mb+SNX_Q7syx!|7$6v26o^eiy+Dw+n|& z@1M7+E9{QYM#g^R(dol5#6S8ICf)%%QXgve`ocUmFyySt*{8=WB@3UmB}b*Y)P?#d zW<^!m47*J)?f}$=K z3M6mbgd*1=tdiZ4rOy4c;lldYWfu@-Zp~T3LpsGFe1TiZ@=HZ7x$IAmO}gd0Y)jrQ z%Qr_l4>~ZhO{E*myVdEqn3P6>fT;SAX}vlG`D$<-IZ%|GuqlmYe@GdjHc*Ulxd!A| zWInZCzuj(Y=1m|~|ATj(lBwA+m5rp#g#fin{aFEn=+o>sg0`E6ECV(cJZ}f+xlQ!C zDHWzpq*}Rpmzj16!!;It28`x71+_@|4VBQ{S>_Kvj3^H??R9T?OGUicf}8*+h*lZo znC-YhQcDzqr+`V0-Xv=`DFdz1Rq2ECZGROOKg_E>y_`&@#Rii4qvJx?t$4mpzNpbUEmXI!a%_mO2Vn^I$Wjq?{ z;HLnEJk^ix>{p-n#pzW0ypC#os`kIW$5DZu0m{;@OIyL zWSCLM1jDh1c5f#{8kx}ybkN?(m{AJ)m-f9Wkr~;A#8^P*JXu_6n2^50dL}S^8F5J% z$u2&Nt>`}i`IpPaO+GIpZ7Wk9G_`TAUo-rWE^CAO^R9wg^ofB={~U3ZZ0F*=@iYce zD*g4nm73mDxTck_?u^x_nq^D*_{mrS_Nn~TvJJFYo>Xz=gs;;Bf5_?P3yD8nH718X zUz%v1NVD23LEv%`%~+j{&!C(@)C8ljTsFEC%s|D0tovGpo$UvPe$zlL5PI2=PQ*fq zb+nGaGrI|K3x}L5Yj57%Yzf}Emw|>e2i^}RxL@3K9(O{Tyv%*y9*X$e(;2_?d^7+d zQ6cIOVe+*&wC!+LpIt4a&?`a#b0`7LVtH1r*kD;&U2Xcu;VoesX_<-Jt1T_`URLOZ zmCw@Wwto2{Uz)&qEOS#`n1=s|L^Wj@PZtZ6xCHdc@G8gA@h9O(tnDD-_VG3o;XTL1 zeKQrHwza?E+++MLx~jaYfss$M%I0d}gH1|(z1df5I21IQoFod?{pT$O%(if)im)D* zGdUCQIJ&)SRno0~=e?SqYb(qhdx;t-%$9=+Fjz7T<~R*v^5I3;D%PUI4e;qm?>_Cx zBR97~U-ia3ta|#1QjQlhZ~j>+s;9lv)ub_If`LylUnlojTeF0FBfAjwEi4K>dsepW zYH_NiX}51syqbbGqeyv+)^bqvH;HiJElstg$u8hBOm>B=rwIFPK=1OUci6f3Wxg!D z(kEo{pfCPe$8z^rIYXRZp)AyuBk=BKy7lzopVuO(*KN7fitiv_m)%6WP%#xO9O5ev zySD&c{@NUHG~RfI7^EX!>A=Neg{%NHHuTMv3fNw}-gS6%?<`!GdjhN<+2%E`d==w&nh0&n(gsYKT33Yk< zr%(PZ}Oy=l3pVh@|h%WS}547CCCiP^xSgu)VGfP0~px6SI$$@e35OLF+j595) zK?3UqYpVm(9oAh|@;A_*z)>tW)4LUrtJtgnR~TNPHg5l3xSAgoc&RSyPVR7<{im%y zY6)y-P1)RR)t9`qjo@*rgx(yiE&%(ZF%D4V_WSt*FHCYnNGA5X9kr$a=d85-Ie}Zz zon*|rX>1VGQ}F=Oe@cJwXH;HMTvFlm#&Vi6CIbG%PrEy3hN&y`b>;>%8J*IH^|@^s z6U}Mb{513BV2yF(DMU|;1L_4#%P8OB>&Etd@rQ%3lu|zUl{z^Wgsa1#__HDU`IHQB zUiC-VF(olSL%vH}LH_cuWuc~YF~B)>qjf@f0txu&)^YFx+66IcrB`JTKuLz%IdN;1pd_4QQNMVN9u+=r3;$LVe3=78#M zmW{!IPBq*>T=IMM3lA~DX*Lhtgsp2lL9L6GPM?~PamtnJ&cfg9*SxtVEf;c4*^J?S zgPbng62ijE3%VsUElcr;U`QSMXykV{qrYVhnqKVZ*a^2Xm6N21p7m?MK>DL5dDC?}OKO?> z4X^5V_0nCfnY%o{6{&03H1K<#y`4N;Uvo-F@mcYDnGhG{TxQn-tK>wZn@sGRalgst z;=H9Zj$OZ1*2Slns}qtW zYr0V=BEt~!Z=DC$q_pbFL$)W!KCh)eKi-hV%ua7B;jib^Ma2>%P%@Q>;=gfivNhTP zH_NEaIQ%C*N1=S+$3ocj)}NF&sgBR<^6FUCFBb^5q^uWd*GNS4yGTANjd~F96rcV8 zUSgQ@ifMC~N^;CGPw+L_Kjk4`@3Sb1=_c9HqZ)Y^m(?~Avh+E z63t_8jle(s#9~ikI>EXfDCh(`$x`;0Bi2qHED0hrg30(WBaaBvewa~;gC4-5JTmEn zmxq^Q1JgZiG?rg{Krh)0WZaeP4jZ-!;UPTte0~SGY8K~OGp%4{?(42ZXbpx z=MBHjWm8`&tI6N`7B?LvX4!l?-X$&}QPQ$Wy0*s}C$5R>83?2rGTYdY{~qPb=701a zIZ|x<(PWdwSks?`nUpb-2Spwe`qHr@)q_ynfx;8W?IX1B4TCHWy@Yrfd z@^Zg@%R-{4+H(8TKgF3(6jws40nZmuD2-Lexx{0U?~-4Xjr@R4Ah)LH9Q(s7Pjm^5a{K6_J_?4No=3E4BolRBPEmZdClFY!yEc9vdWmx8O^_ zl6hp&8vqm-UNgRYI+UXGrG1bGm+8+g$uDutlFn`nTR8p(6(w3~sWaoR0fpF$WpWKT zAgr$c`YNpI?yo=J@O@68>UP6erNL)^>>4lnq3%#~NNI{dZ;m)zj?+|+sY|Um*{IsK z>Yte^TQ14f;rf~F2<#vxHw4FRcb%5{h!1Hu{0eKeERRU!dTe&=p|sHX{5LXD7NNt~$(C6jA z=N(4E#gUSR4GePkgRhFtL&&n%D0^WDaDLC+(tW5M8oF&%jor!+?~+g-U{wjucn6=X zJNn~kN{U|WJLlyd(LouA@eopXW~@VVo2Q=pr-0S8FUC%x|C06ft{Z;K?1rUl=(H>b zwFe;l=XtF4Z?qSl_VlGvj|(_|9}IyKlt^CD07nkn%(t2NW;TF;x(@k}TL-KOk+b)7 zX2jSO-n$^y>1GnIRr5muRX7sBS_QS7Q#9-a3d%k=rr+PKCR9_-)0*!4-LC1g+H^7# z>Z$2{$SMNz13hMpqh6b0aO&#oT{4m*=QS2mNJZdLO*iQ8vV~ylthn8ehoE z=(=8D-6FX@FpEeHEgppn33n-MF5OQ?{O0=Ao)6yfK+Ozf$Ah>b)g=C=l{rybhDhKs z)sM%Ssd3N3^>5X)&wPZZ_)m;cD}}e7PTd+u+qdPD7fQf|+gx+Rzt7|SQ*btHKB&(1 ztNS5tCJI}{@hLW^!{tLnlUq)7Iokmry*sh2&g7{x%0i>-pRp631~-cx#(4_!egw=$ z>4T^g7b0muRXe70j$fx8gEeyu>5LQ1~O1oY#}DXxt9mb<;qi2y@XvzrY0LSkyn^ z+UKuP1F=U9x8kqq*DmWXEf5 z9GM0QF>Y+%(h!UIlPa6g)OrcBBpnq zE8dBSNmI1q^MK5{9h2!ix#@But1qry? zoR4^$hVnHpwr*>tz7wG#bdHBL+kyO|QF3Z#)IxI7&_=8OQ{ArbkR)CDVB-jE$(q;v zP`ui<>3#JNEm!)sgVI)c=-f0Nrc2*jW5Q~4L}==MfJZUj3_2BAIH;?rHuQ*KIo$&J z*>8MzJ5S}ejNR&a{-Cd?McY)u;M7DUxICse>*mfyI$Yb11veqknyR_^4v9mN_1Ex4 z9Qo0ZaDl;qi;vZ?XYf%I3~sD!ICzdlWE|qmZ-FaQMnBH@q(#tt0UidaQG6Og9hgTgqt>-6C-9lke`NfsHAYY)5%w7ju zQ!!lnkoZ$m2mmS)4M^e-go~u|rGTT%>t|CwGxS~p+WJX9cg76)!z&`k@;bAn-f(-) z%%t1J$ga|{3B}sN>{0v7KXhCX5}D(k+Ng$3-Kcs$p^24@@Gxy7sJntjsWL=yH5Q!S z;vHQ$Bnw^Y@9*1&+hrN54ht4Vc2F@pZ=rYOJTfFtc+frJ!i`=0daG?y?!x@Pn%?yV z9OW_>>2cLpx z+gihAi%(Np>6eG}1XgxFLVG|h+fJd{hde4GKV}JeqC3*5YJkD?thmFt=fen_1ljqk zuMuBvU3lo5^&-%TyHEAp$GgK5b;E&IQ)@%)9x+%ULbl7WRg$tP@5uvety+Fdqzq}= zFW%Ar`SrSh7AGfqt0&W9a9MIzE6Vq%AwJ~i-K6W(#mlPBzh2~zt3Ep9q|iKVyftu( zE@5ix33(r82L63=D*s_$5ke>1N)e*a!RNM`bHatS=lxocF1=Y?kxMt;-73sHhL)5- z*NZJz=1vZuf?Y^VUz;x8s=gSOA+REP%%hEVgoo%H0`Bev*g;M#PPqDx`H8P>2k)~| zg_LmM6vpdJ)|U7@s$l7Ee>uYnx3dWtwFXrt6iB8+ojYVoSOUa$Oi7CJb?z z8mh^+I;}rGk@$HW5q!~4IG|ysqUj~7>9KRwK1inBbbPm_lX_moOpozxvJY`i5Rw|dKy66p|@yO8Vr zQg8lnPG_y7-K~r1*K1#SI30b(>o(m5eYom2n=BtjU>J9q#>+^1@FcD;ei+ZytsD9Zuz0 zvG7zYSMO;6oBsGor5or|mMNxrIS~)WXS*hjIAQ37rqlA%owJPF_?Y0977`lEpQC*qGx+S*|o~>3jRBTLKr;VJ)F&m%*U35nV;yGe3~W zOozXhpqg3opQ$cub`>g5nok|B1}?a7=nd1d;>P)s>+r=E6%eduRdaB^tR#$xC~PSR zy;l^qYRQzkVc)~wB-B#>Eltd3Dl$U%A*yU~;nr49U%c8dWbjqO)9yRlp?CF}K&L8N z>VJ>VRu2S7+lBl}pT!=VCE}tEykE2vZ-RN;!6<*kS20SG5@DW%)05(Wtded0Ri>HaU0$Mg}kay+tz3+ue}KS;oOX=0?rf&WZHeg5n5a2qZ2g za=86Pqbm4|tJjQ+6{3&(ZlhK|gY}448sYwlj|cT$)@ICopMTl{GZe4=?6dX?Pn|1n z-JR{Ld{b`iRu!{L`NWz_^Q@l>*ZtmdW7Xy2&Gq{vO^tBJ&-|+_f$1c*e)MCP=Kzi)h3K!~C3tIn^7etN8i-iPE4a7$zmfvsuk_q&!cnbwy}?_fp?)6aU%9F8Qol3s zde_y7p)0K|!=8!egWFQqcm(AQHfo@ovYB(BM&S{99O+P_yHlz40esVf@V2&&01NdmzUE<=lx zSIq6;_rCjQUk;Fb*>E%+s$@DVV ze2lPiV0+JL-ksybi*bbPuT)}m6CN&<&D!vSl2b}x|L}>uY|u=oU8BEKAzJJpbHVcD zrMn3)Jf%V?1yipwQEWqh{T~pr8cIPMG9MWLws>4f=ZnYB6PAqs(V*%sdQNbL^q7%I zEx)rF{Qf>boe*X+ctSR{m!qG8aI{%dvFz?%>LZolO)ymS3b|F^fci$Z!4V32?}}2z z{F^MS_2=YLZ=~?&DdWdW)bPlCAF5fH{TSs|ct6}}cL3s9`XvjWFm*-C+Rf?gL56l# z7=4WlZc`h|t&-C4eMq0>u;~|>a}^x>%isOiE||mj9T>={3L$eK@s_AVVgh`w*mDNf z11=2MNKE4d1T~oOia0r8Exsj(AbTXC`3WSLx8I9U-sSO!#(f+cQ07hg;L zB7+O_8kNp3clw6X8DZ(cYyd!$QLCd#OP4x#@9JI;bpi#!4+47c+%OM#=47At9{(N# zp2GbP>fZ#XkCGgNL$Q1gJT6+7dLHQJ@o+C*AtO`ziQshc)1va7f7|%9pCuvVx#wQE@76pDs_0v`E(CtKldVEWa`zzg*NGOjuDK9=Gk%pq(x(5d zZt-~-{Xtr*M)daI-P&vTDrUWXuv>y+WX_Z-cpN)`d2J)OBV20k?ytm0(S3=)7kUk_ zBvP+-Hlo+%E_IG<>VN=yR2}QdDNKD{+D1TZ1J+FK<%s}S8fbwnvRx1sk~!p|L$bCz zgMrn5&}q^DE^A4KP1q}H*kcp-DUVakN2IkbJpasmes2*3*^#oL0=xLHDDLB%DxTww zh5y-oU`Oo5ia;7}al9@RL)vZe87iVUFq4p&Hn-DG1>yY*kB{`x)(1!Ceh9!34J)-* z`N-aIRcI2;0cZxMK}TlMtlfJz8axC{7z-3cCRWV;bAQqLy9pGMTz#&ixSt5Vpyq&7py;3Kf>s zAKz}ct@w#pX(y{#p_zTHKx1N|6oJf!YXEn540DuW&;lAJ(yS!H+7P_tqR0NsS0yL1i+Hwjr5 zxo0VmrS9M+%eR}B??!p`$xf{A5$VmjjF&dcS%%?=q+QYi=&$qMpJ_e-Tlud6;gIGw zC7B?E`cx?KsM=~9F{7Y2ptJw3a2s%wN-Vl?PueJ5q7r;b{4J3gKH7j_{|>Nk><304;kE?>af8*BjSWh|W#jzN}HvN{`m+An!@BubpIBAdhs(etVZT|4> z;NPU`DOMck4d?7-E(jev;sea9pe7hHx_}H+pV|yk%kG!zsPL0E5iD0U4IVQ2??;LK zWyvbJNAfCFq&pf$6t*i5q`#sC^$zKryI?8&vjUstr#H*ls*JXV=?y~&<~Ev)>@SmK zj4zT588(OqnD)bT(G0t)M*r1)JC?^otHxfL89bnXUwqAFL2Ki&O-Fb2b=2E|E7`>I zu3a$!pBNWVfeZa}H$?+=d~6@Y2-@(I+aAsZfEBUwe`Q~13*z>QfnqO@Y(q!FHQCDH z+YWbjk>9&IMa~#4zC-3Cd_YyB>u>D6L&I!Ik`@4p_tqsdv@8*VUGOU#e|VqJz%Nh` zi&F&MR^e{~{Zeq{)T3uA%h^U5@b8g$d}1&d*3n}+z9+nLH`&eJKS?}(*y9}4`ebnD4aum=52~WTPdUP+@;KEqims9M zD|w}++v;W0iLjop+i1`2{M&G!|CoRL=2YnMoUD0D5ZT?`f^>#&?0={ipv9F0%W1!dG+Ij!M+Wwq;Ri03-Qyv>TT)HvHj6-ywGDpz&t%q-H^#0Pf znc9wM)ux*PfKn^6V2WMY-r1Z=7M}NWsYWBQ0u>DVr-YA81%4-j2D}t=Z%^=V9EPoX zJK$_Yl3DMFu6r%gkTSu74rep%#veW=hT`#|+?l)YwxOta~FxAUhz zH?9fyXO*F$O#-f4@A(}j8fYiIwRaCBAt5qcN~TaSt;8O^vG zrTu0ym8w#YVr*%qvdzCo`;Fd*ofZO8*kN2W7PCzr^C;sYh;($oSqB{^0*g< zF$xL4qOctQN_5cg<;=LLEPd$qs5CyqWJ)SK!z9Wc`;*647uU@E-qzaw>H@Z;cnrpHKbjX9L|>wA1v`smnp#?AAW z=)$jm;vJy>XOVABZcPu%I(xL>0|`6%LQ2a>o*t>@jk?P<6_?rIl^LWFl$!$qeF3jL zHeFd{!#uZKPaghE^#L^4FZ#7vcA~`(H{`dScD$B3Pjvw{9MET1`I?5?mgLRf4aYcC zSnv{13+3rjy~=;U+S4$5x^GwidHenT^H6FP)}-GMzSDv9SWf7oH%4_R;OG&0T_<|a zB}$gNRgUi`knUb(=`LO{1oJG)OBE}ck%;mAxOp1V8r2LAS^61=dK$MtzlKXo7{3Pc z!vDx%FKH7vw`KAED(#W@zit4`Zx21C;pX>nG>~cwlsm_q9_{guuZTu(`ag_$ZFO2}7lmTUY>K@jV zgL`Ml-iZHK=_R4=7B7dudV@ z8;Qlf8t(4v|6C=&nN<8dYVNmsyinr6ggZ<9`%<=hgcFNC!PA4_mS*|$Mfkq?D@PINQV$m#9wrtx_|2^;|rvO|Ph|##Op#^9lvY11>gA)_WF`$lPd*-OY zj8t%Vz{41fq7Z0lEh8t)KuJc`wP&vMmgaUzxn3UiaRQ z|1h19>sdIyu&MwJJkZ@R=^A%mJi@_wLI&F4KtLFML43jln1K)cfR3{Mo|Xj+v^PQ@ z^zbN!2G lfsPointerMaxSize { + return lfsPointer{}, false + } + + lines := strings.Split(strings.TrimSuffix(string(data), "\n"), "\n") + if len(lines) < 3 || lines[0] != lfsVersionLine { + return lfsPointer{}, false + } + + ptr := lfsPointer{size: -1} + for _, line := range lines[1:] { + if oid, ok := strings.CutPrefix(line, "oid sha256:"); ok { + ptr.oid = oid + } else if raw, ok := strings.CutPrefix(line, "size "); ok { + n, err := strconv.ParseInt(raw, 10, 64) + if err != nil { + return lfsPointer{}, false + } + ptr.size = n + } + } + + if !validOID(ptr.oid) || ptr.size < 0 { + return lfsPointer{}, false + } + return ptr, true +} + +func validOID(oid string) bool { + if len(oid) != 64 { + return false + } + for _, c := range oid { + if (c < '0' || c > '9') && (c < 'a' || c > 'f') { + return false + } + } + return true +} diff --git a/internal/archive/transform.go b/internal/archive/transform.go new file mode 100644 index 0000000..9c3ff80 --- /dev/null +++ b/internal/archive/transform.go @@ -0,0 +1,58 @@ +package archive + +import ( + "archive/tar" + "bytes" + "io" +) + +type SmudgeFunc func(oid string) (io.ReadCloser, int64, error) + +func Transform(src io.Reader, prefix string, smudge SmudgeFunc, enc Encoder) error { + tr := tar.NewReader(src) + for { + hdr, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return err + } + // drop the pax global header (the commit sha comment git emits) + if hdr.Typeflag == tar.TypeXGlobalHeader { + continue + } + hdr.Name = prefix + hdr.Name + + if err := writeEntry(enc, hdr, tr, smudge); err != nil { + return err + } + } + return enc.Close() +} + +func writeEntry(enc Encoder, hdr *tar.Header, body io.Reader, smudge SmudgeFunc) error { + // only small regular files can be LFS pointers, everything else passes through + if smudge == nil || hdr.Typeflag != tar.TypeReg || hdr.Size > lfsPointerMaxSize { + return enc.Write(hdr, body) + } + + data, err := io.ReadAll(body) + if err != nil { + return err + } + ptr, ok := parseLFSPointer(data) + if !ok { + return enc.Write(hdr, bytes.NewReader(data)) + } + + rc, size, err := smudge(ptr.oid) + if err != nil { + // missing or foreign object: keep the pointer bytes, never fail the archive + return enc.Write(hdr, bytes.NewReader(data)) + } + defer rc.Close() + + hdr.Size = size + return enc.Write(hdr, rc) +} diff --git a/internal/archive/transform_test.go b/internal/archive/transform_test.go new file mode 100644 index 0000000..b6dae30 --- /dev/null +++ b/internal/archive/transform_test.go @@ -0,0 +1,212 @@ +package archive + +import ( + "archive/tar" + "archive/zip" + "bytes" + "compress/gzip" + "errors" + "fmt" + "io" + "strings" + "testing" +) + +func TestParseLFSPointer(t *testing.T) { + oid := strings.Repeat("ab", 32) + valid := "version https://git-lfs.github.com/spec/v1\noid sha256:" + oid + "\nsize 12345\n" + + cases := []struct { + name string + data string + ok bool + }{ + {"valid", valid, true}, + {"empty", "", false}, + {"plain text", "hello world\nthis mentions oid sha256: things\nsize 5\n", false}, + {"wrong version", "version https://example.com/spec/v1\noid sha256:" + oid + "\nsize 5\n", false}, + {"short oid", "version https://git-lfs.github.com/spec/v1\noid sha256:abcd\nsize 5\n", false}, + {"missing size", "version https://git-lfs.github.com/spec/v1\noid sha256:" + oid + "\n\n", false}, + {"bad size", "version https://git-lfs.github.com/spec/v1\noid sha256:" + oid + "\nsize lots\n", false}, + {"oversized", valid + strings.Repeat("x", lfsPointerMaxSize), false}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ptr, ok := parseLFSPointer([]byte(tc.data)) + if ok != tc.ok { + t.Fatalf("parseLFSPointer ok = %v, want %v", ok, tc.ok) + } + if ok && (ptr.oid != oid || ptr.size != 12345) { + t.Errorf("parseLFSPointer = %+v", ptr) + } + }) + } +} + +// builds a tar the way git archive would emit it: pax global header first, +// then dirs, files (including an LFS pointer), and a symlink +func buildTestTar(t *testing.T, pointer string) []byte { + t.Helper() + var buf bytes.Buffer + tw := tar.NewWriter(&buf) + + write := func(hdr *tar.Header, body string) { + t.Helper() + if err := tw.WriteHeader(hdr); err != nil { + t.Fatal(err) + } + if body != "" { + if _, err := tw.Write([]byte(body)); err != nil { + t.Fatal(err) + } + } + } + + write(&tar.Header{ + Typeflag: tar.TypeXGlobalHeader, + Name: "pax_global_header", + PAXRecords: map[string]string{"comment": strings.Repeat("a", 40)}, + Format: tar.FormatPAX, + }, "") + write(&tar.Header{Typeflag: tar.TypeDir, Name: "src/", Mode: 0o755}, "") + write(&tar.Header{Typeflag: tar.TypeReg, Name: "README.md", Mode: 0o644, Size: 6}, "hello\n") + write(&tar.Header{Typeflag: tar.TypeReg, Name: "src/big.bin", Mode: 0o644, Size: int64(len(pointer))}, pointer) + write(&tar.Header{Typeflag: tar.TypeSymlink, Name: "link", Linkname: "README.md", Mode: 0o777}, "") + + if err := tw.Close(); err != nil { + t.Fatal(err) + } + return buf.Bytes() +} + +func readZip(t *testing.T, data []byte) map[string]string { + t.Helper() + zr, err := zip.NewReader(bytes.NewReader(data), int64(len(data))) + if err != nil { + t.Fatal(err) + } + got := map[string]string{} + for _, f := range zr.File { + rc, err := f.Open() + if err != nil { + t.Fatal(err) + } + body, err := io.ReadAll(rc) + rc.Close() + if err != nil { + t.Fatal(err) + } + got[f.Name] = string(body) + } + return got +} + +func smudgeFrom(objects map[string]string) SmudgeFunc { + return func(oid string) (io.ReadCloser, int64, error) { + content, ok := objects[oid] + if !ok { + return nil, 0, errors.New("object not found") + } + return io.NopCloser(strings.NewReader(content)), int64(len(content)), nil + } +} + +func TestTransformZipSmudgesLFS(t *testing.T) { + oid := strings.Repeat("ab", 32) + content := "REAL LFS CONTENT, MUCH BIGGER THAN A POINTER" + pointer := fmt.Sprintf("version https://git-lfs.github.com/spec/v1\noid sha256:%s\nsize %d\n", oid, len(content)) + + var out bytes.Buffer + src := bytes.NewReader(buildTestTar(t, pointer)) + if err := Transform(src, "repo-abc/", smudgeFrom(map[string]string{oid: content}), NewZipEncoder(&out)); err != nil { + t.Fatal(err) + } + + got := readZip(t, out.Bytes()) + if _, ok := got["repo-abc/src/"]; !ok { + t.Errorf("missing dir entry, got %d entries", len(got)) + } + if got["repo-abc/README.md"] != "hello\n" { + t.Errorf("README.md = %q", got["repo-abc/README.md"]) + } + if got["repo-abc/src/big.bin"] != content { + t.Errorf("big.bin not smudged: %q", got["repo-abc/src/big.bin"]) + } + if got["repo-abc/link"] != "README.md" { + t.Errorf("symlink target = %q", got["repo-abc/link"]) + } + if _, ok := got["repo-abc/pax_global_header"]; ok { + t.Error("pax global header leaked into the archive") + } +} + +func TestTransformKeepsPointerWhenObjectMissing(t *testing.T) { + oid := strings.Repeat("ab", 32) + pointer := fmt.Sprintf("version https://git-lfs.github.com/spec/v1\noid sha256:%s\nsize 44\n", oid) + + var out bytes.Buffer + src := bytes.NewReader(buildTestTar(t, pointer)) + if err := Transform(src, "repo-abc/", smudgeFrom(nil), NewZipEncoder(&out)); err != nil { + t.Fatal(err) + } + + if got := readZip(t, out.Bytes())["repo-abc/src/big.bin"]; got != pointer { + t.Errorf("missing object should keep pointer bytes, got %q", got) + } +} + +func TestTransformWithoutSmudge(t *testing.T) { + oid := strings.Repeat("ab", 32) + pointer := fmt.Sprintf("version https://git-lfs.github.com/spec/v1\noid sha256:%s\nsize 44\n", oid) + + var out bytes.Buffer + src := bytes.NewReader(buildTestTar(t, pointer)) + if err := Transform(src, "repo-abc/", nil, NewZipEncoder(&out)); err != nil { + t.Fatal(err) + } + + if got := readZip(t, out.Bytes())["repo-abc/src/big.bin"]; got != pointer { + t.Errorf("nil smudge should keep pointer bytes, got %q", got) + } +} + +func TestTransformTarGz(t *testing.T) { + oid := strings.Repeat("ab", 32) + content := "REAL LFS CONTENT" + pointer := fmt.Sprintf("version https://git-lfs.github.com/spec/v1\noid sha256:%s\nsize %d\n", oid, len(content)) + + var out bytes.Buffer + src := bytes.NewReader(buildTestTar(t, pointer)) + if err := Transform(src, "repo-abc/", smudgeFrom(map[string]string{oid: content}), NewTarGzEncoder(&out)); err != nil { + t.Fatal(err) + } + + gz, err := gzip.NewReader(bytes.NewReader(out.Bytes())) + if err != nil { + t.Fatal(err) + } + got := map[string]string{} + tr := tar.NewReader(gz) + for { + hdr, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + t.Fatal(err) + } + body, err := io.ReadAll(tr) + if err != nil { + t.Fatal(err) + } + got[hdr.Name] = string(body) + } + + if got["repo-abc/src/big.bin"] != content { + t.Errorf("big.bin not smudged: %q", got["repo-abc/src/big.bin"]) + } + if got["repo-abc/README.md"] != "hello\n" { + t.Errorf("README.md = %q", got["repo-abc/README.md"]) + } +} diff --git a/internal/domain/archive.go b/internal/domain/archive.go new file mode 100644 index 0000000..3fbbd94 --- /dev/null +++ b/internal/domain/archive.go @@ -0,0 +1,46 @@ +package domain + +import "fmt" + +type ArchiveFormat string + +const ( + ArchiveFormatZip ArchiveFormat = "zip" + ArchiveFormatTarGz ArchiveFormat = "tar.gz" +) + +func ParseArchiveFormat(s string) (ArchiveFormat, bool) { + switch s { + case "", "zip": + return ArchiveFormatZip, true + case "tar.gz", "tgz": + return ArchiveFormatTarGz, true + } + return "", false +} + +func (f ArchiveFormat) Extension() string { + if f == ArchiveFormatTarGz { + return "tar.gz" + } + return "zip" +} + +type ArchiveRequest struct { + Repository Repository + CommitSHA string + Format ArchiveFormat + IncludeLFS bool +} + +// Filename is the suggested artifact name: -. +func (r ArchiveRequest) Filename() string { + return fmt.Sprintf("%s-%s.%s", r.Repository.RepositoryName, ShortSHA(r.CommitSHA), r.Format.Extension()) +} + +func ShortSHA(sha string) string { + if len(sha) > 12 { + return sha[:12] + } + return sha +} diff --git a/internal/gitbackend/backend.go b/internal/gitbackend/backend.go index 9815790..ff98705 100644 --- a/internal/gitbackend/backend.go +++ b/internal/gitbackend/backend.go @@ -13,4 +13,6 @@ type Backend interface { UploadPack(ctx context.Context, storagePath string, stateless bool, stdin io.Reader, stdout, stderr io.Writer) error ReceivePack(ctx context.Context, storagePath string, stateless bool, stdin io.Reader, stdout, stderr io.Writer) ([]RefChange, error) ListTree(ctx context.Context, storagePath, rev, treePath string) (TreeListing, error) + ResolveCommit(ctx context.Context, storagePath, rev string) (string, error) + ArchiveTar(ctx context.Context, storagePath, rev string, out io.Writer) (string, error) } diff --git a/internal/gitbackend/local.go b/internal/gitbackend/local.go index 94ac2ff..2520c7b 100644 --- a/internal/gitbackend/local.go +++ b/internal/gitbackend/local.go @@ -206,11 +206,12 @@ func (l *Local) ListTree(ctx context.Context, storagePath, rev, treePath string) return TreeListing{}, err } - rev, err = normalizeRev(rev) + treePath, err = normalizeTreePath(treePath) if err != nil { return TreeListing{}, err } - treePath, err = normalizeTreePath(treePath) + + commitSHA, err := l.ResolveCommit(ctx, storagePath, rev) if err != nil { return TreeListing{}, err } @@ -218,11 +219,6 @@ func (l *Local) ListTree(ctx context.Context, storagePath, rev, treePath string) ctx, cancel := context.WithTimeout(ctx, l.timeout) defer cancel() - commitSHA, err := l.revParse(ctx, dir, rev+"^{commit}") - if err != nil { - return TreeListing{}, fmt.Errorf("%w: %s", ErrRevNotFound, rev) - } - treeish := commitSHA if treePath != "" { treeish += ":" + treePath @@ -244,6 +240,52 @@ func (l *Local) ListTree(ctx context.Context, storagePath, rev, treePath string) return TreeListing{CommitSHA: commitSHA, Entries: entries, Truncated: truncated}, nil } +// streams an uncompressed tar archive of the repo tree, +// the tar entries carries LFS pointers files as-is, smudging is a service concern! +func (l *Local) ArchiveTar(ctx context.Context, storagePath, rev string, out io.Writer) (string, error) { + dir, err := l.resolve(storagePath) + if err != nil { + return "", err + } + + // only the resolution step gets the short timeout + commitSHA, err := l.ResolveCommit(ctx, storagePath, rev) + if err != nil { + return "", err + } + + cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "archive", "--format=tar", "--end-of-options", commitSHA) + cmd.Stdout = out + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("git archive: %w: %s", err, strings.TrimSpace(stderr.String())) + } + return commitSHA, nil +} + +func (l *Local) ResolveCommit(ctx context.Context, storagePath, rev string) (string, error) { + dir, err := l.resolve(storagePath) + if err != nil { + return "", err + } + + rev, err = normalizeRev(rev) + if err != nil { + return "", err + } + + ctx, cancel := context.WithTimeout(ctx, l.timeout) + defer cancel() + + // ^{commit} forces the object to exist and peel to a commit + commitSHA, err := l.revParse(ctx, dir, rev+"^{commit}") + if err != nil { + return "", fmt.Errorf("%w: %s", ErrRevNotFound, rev) + } + return commitSHA, nil +} + // revParse resolves a rev expression to an object id, failing when the object does not exist func (l *Local) revParse(ctx context.Context, dir, spec string) (string, error) { cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "rev-parse", "--verify", "--end-of-options", spec) diff --git a/internal/gitbackend/local_test.go b/internal/gitbackend/local_test.go index 4d512c5..0031f38 100644 --- a/internal/gitbackend/local_test.go +++ b/internal/gitbackend/local_test.go @@ -1,9 +1,12 @@ package gitbackend import ( + "archive/tar" + "bytes" "context" "errors" "fmt" + "io" "os" "os/exec" "path/filepath" @@ -12,6 +15,19 @@ import ( "testing" ) +// runs a git command in dir with a deterministic identity, failing the test on error +func gitRun(t *testing.T, dir string, args ...string) { + t.Helper() + cmd := exec.Command("git", append([]string{"-C", dir}, args...)...) + cmd.Env = append(os.Environ(), + "GIT_AUTHOR_NAME=t", "GIT_AUTHOR_EMAIL=t@t", + "GIT_COMMITTER_NAME=t", "GIT_COMMITTER_EMAIL=t@t", + ) + if out, err := cmd.CombinedOutput(); err != nil { + t.Fatalf("git %v: %v: %s", args, err, out) + } +} + func TestResolveContainment(t *testing.T) { root := "/srv/repos" l := &Local{root: root} @@ -172,18 +188,7 @@ func TestListTree(t *testing.T) { // build a working tree and push it to a known branch name wt := filepath.Join(t.TempDir(), "wt") - git := func(dir string, args ...string) { - t.Helper() - cmd := exec.Command("git", append([]string{"-C", dir}, args...)...) - cmd.Env = append(os.Environ(), - "GIT_AUTHOR_NAME=t", "GIT_AUTHOR_EMAIL=t@t", - "GIT_COMMITTER_NAME=t", "GIT_COMMITTER_EMAIL=t@t", - ) - if out, err := cmd.CombinedOutput(); err != nil { - t.Fatalf("git %v: %v: %s", args, err, out) - } - } - git(".", "clone", filepath.Join(root, "1/test.git"), wt) + gitRun(t, ".", "clone", filepath.Join(root, "1/test.git"), wt) writeFile := func(rel, content string, mode os.FileMode) { t.Helper() full := filepath.Join(wt, rel) @@ -197,9 +202,9 @@ func TestListTree(t *testing.T) { writeFile("README.md", "hello\n", 0o644) writeFile("src/main.go", "package main\n", 0o644) writeFile("src/run.sh", "#!/bin/sh\n", 0o755) - git(wt, "add", "-A") - git(wt, "commit", "-m", "init") - git(wt, "push", "origin", "HEAD:refs/heads/main") + gitRun(t, wt, "add", "-A") + gitRun(t, wt, "commit", "-m", "init") + gitRun(t, wt, "push", "origin", "HEAD:refs/heads/main") t.Run("root listing", func(t *testing.T) { listing, err := l.ListTree(ctx, "1/test.git", "main", "") @@ -260,6 +265,99 @@ func TestListTree(t *testing.T) { }) } +func TestArchiveTar(t *testing.T) { + if _, err := exec.LookPath("git"); err != nil { + t.Skip("git not on PATH") + } + + root := t.TempDir() + l, err := NewLocal(root) + if err != nil { + t.Fatal(err) + } + ctx := context.Background() + + if err := l.InitBare(ctx, "1/test.git"); err != nil { + t.Fatal(err) + } + + // empty repo: HEAD is unborn + if _, err := l.ArchiveTar(ctx, "1/test.git", "", io.Discard); !errors.Is(err, ErrRevNotFound) { + t.Fatalf("empty repo: want ErrRevNotFound, got %v", err) + } + + // an LFS-pointer-shaped blob: the archive must carry it byte-for-byte, + // smudging is explicitly not this layer's job + pointer := "version https://git-lfs.github.com/spec/v1\n" + + "oid sha256:" + strings.Repeat("a", 64) + "\n" + + "size 12345\n" + + wt := filepath.Join(t.TempDir(), "wt") + gitRun(t, ".", "clone", filepath.Join(root, "1/test.git"), wt) + files := map[string]string{ + "README.md": "hello\n", + "src/main.go": "package main\n", + "big.bin": pointer, + } + for rel, content := range files { + full := filepath.Join(wt, rel) + if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(full, []byte(content), 0o644); err != nil { + t.Fatal(err) + } + } + gitRun(t, wt, "add", "-A") + gitRun(t, wt, "commit", "-m", "init") + gitRun(t, wt, "push", "origin", "HEAD:refs/heads/main") + + var buf bytes.Buffer + sha, err := l.ArchiveTar(ctx, "1/test.git", "main", &buf) + if err != nil { + t.Fatal(err) + } + if len(sha) != 40 { + t.Errorf("want 40-hex commit sha, got %q", sha) + } + + // the stream must be a valid tar containing exactly the committed files + got := map[string]string{} + tr := tar.NewReader(&buf) + for { + hdr, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + t.Fatal(err) + } + if hdr.Typeflag != tar.TypeReg { // skip dirs and the pax global header + continue + } + body, err := io.ReadAll(tr) + if err != nil { + t.Fatal(err) + } + got[hdr.Name] = string(body) + } + if len(got) != len(files) { + t.Fatalf("got %d regular files, want %d: %v", len(got), len(files), got) + } + for rel, content := range files { + if got[rel] != content { + t.Errorf("%s = %q, want %q", rel, got[rel], content) + } + } + + if _, err := l.ArchiveTar(ctx, "1/test.git", "nope", io.Discard); !errors.Is(err, ErrRevNotFound) { + t.Errorf("unknown rev: want ErrRevNotFound, got %v", err) + } + if _, err := l.ArchiveTar(ctx, "1/test.git", "--help", io.Discard); !errors.Is(err, ErrInvalidRev) { + t.Errorf("hostile rev: want ErrInvalidRev, got %v", err) + } +} + func TestDiffRefs(t *testing.T) { cases := []struct { name string diff --git a/internal/server/control/repositories/archive.go b/internal/server/control/repositories/archive.go new file mode 100644 index 0000000..ede4e74 --- /dev/null +++ b/internal/server/control/repositories/archive.go @@ -0,0 +1,107 @@ +package repositories + +import ( + "errors" + "fmt" + "io" + "net/http" + "strconv" + + "github.com/Axenos-dev/HeadlessGit/internal/domain" + "github.com/Axenos-dev/HeadlessGit/internal/server/response" + reposervice "github.com/Axenos-dev/HeadlessGit/internal/services/repositories" + "github.com/go-chi/chi/v5" + "go.uber.org/zap" +) + +func (h *handlers) getArchive(w http.ResponseWriter, r *http.Request) error { + id, err := strconv.ParseInt(chi.URLParam(r, "repositoryID"), 10, 64) + if err != nil { + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid repository id") + } + + q := r.URL.Query() + includeLFS := false + if raw := q.Get("lfs"); raw != "" { + includeLFS, err = strconv.ParseBool(raw) + if err != nil { + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "lfs must be a boolean") + } + } + + req, err := h.service.PrepareArchive(r.Context(), id, q.Get("ref"), q.Get("format"), includeLFS) + switch { + case errors.Is(err, reposervice.ErrRepositoryNotFound): + return response.NewError(http.StatusNotFound, response.CodeRepositoryNotFound, "repository not found") + case errors.Is(err, reposervice.ErrRefNotFound): + return response.NewError(http.StatusNotFound, response.CodeRefNotFound, "ref not found") + case errors.Is(err, reposervice.ErrInvalidRef): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid ref") + case errors.Is(err, reposervice.ErrUnsupportedFormat): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "unsupported archive format") + case errors.Is(err, reposervice.ErrLFSNotEnabled): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "lfs is not enabled") + case err != nil: + h.logger.Error("failed to prepare archive", zap.Error(err)) + return response.NewError(http.StatusInternalServerError, response.CodeInternalError, "failed to prepare archive") + } + + etag := archiveETag(req) + if r.Header.Get("If-None-Match") == etag { + w.Header().Set("ETag", etag) + w.WriteHeader(http.StatusNotModified) + return nil + } + + contentType := "application/zip" + if req.Format == domain.ArchiveFormatTarGz { + contentType = "application/gzip" + } + w.Header().Set("Content-Type", contentType) + w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", req.Filename())) + w.Header().Set("ETag", etag) + w.Header().Set("X-HeadlessGit-Commit", req.CommitSHA) + + cw := &countingWriter{w: w} + if err := h.service.StreamArchive(r.Context(), req, cw); err != nil { + // nothing sent yet, + if cw.n == 0 { + // undo the archive headers + w.Header().Del("Content-Type") + w.Header().Del("Content-Disposition") + w.Header().Del("ETag") + w.Header().Del("X-HeadlessGit-Commit") + h.logger.Error("failed to stream archive", zap.Int64("repository_id", id), zap.Error(err)) + // and return normal error + return response.NewError(http.StatusInternalServerError, response.CodeInternalError, "failed to stream archive") + } + + // otherwise just log, the bytes were already streamed + h.logger.Error("archive stream aborted mid-flight", + zap.Int64("repository_id", id), + zap.Int64("bytes_written", cw.n), + zap.Error(err), + ) + } + return nil +} + +func archiveETag(req domain.ArchiveRequest) string { + variant := string(req.Format) + if req.IncludeLFS { + variant += "-lfs" + } + return fmt.Sprintf(`W/"%s-%s"`, req.CommitSHA, variant) +} + +// just to keep track how much bytes were streamed +type countingWriter struct { + w io.Writer + n int64 +} + +func (c *countingWriter) Write(p []byte) (int, error) { + n, err := c.w.Write(p) + c.n += int64(n) + return n, err +} diff --git a/internal/server/control/repositories/archive_test.go b/internal/server/control/repositories/archive_test.go new file mode 100644 index 0000000..030b322 --- /dev/null +++ b/internal/server/control/repositories/archive_test.go @@ -0,0 +1,116 @@ +package repositories + +import ( + "archive/zip" + "bytes" + "encoding/json" + "io" + "net/http" + "net/http/httptest" + "testing" + + "github.com/Axenos-dev/HeadlessGit/internal/domain" + reposervice "github.com/Axenos-dev/HeadlessGit/internal/services/repositories" +) + +func testArchiveRequest() domain.ArchiveRequest { + return domain.ArchiveRequest{ + Repository: domain.Repository{ID: 7, RepositoryName: "myrepo"}, + CommitSHA: testSHA, + Format: domain.ArchiveFormatZip, + } +} + +func TestGetArchive(t *testing.T) { + router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), streamBody: "hello"}) + + rec := httptest.NewRecorder() + router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/repositories/7/archive?ref=main", nil)) + + if rec.Code != http.StatusOK { + t.Fatalf("status = %d, body %s", rec.Code, rec.Body.String()) + } + if got := rec.Header().Get("Content-Type"); got != "application/zip" { + t.Errorf("Content-Type = %q", got) + } + if got := rec.Header().Get("Content-Disposition"); got != `attachment; filename="myrepo-aaaabbbbcccc.zip"` { + t.Errorf("Content-Disposition = %q", got) + } + if got := rec.Header().Get("ETag"); got != `W/"`+testSHA+`-zip"` { + t.Errorf("ETag = %q", got) + } + if got := rec.Header().Get("X-HeadlessGit-Commit"); got != testSHA { + t.Errorf("X-HeadlessGit-Commit = %q", got) + } + + // the body must be a readable zip + zr, err := zip.NewReader(bytes.NewReader(rec.Body.Bytes()), int64(rec.Body.Len())) + if err != nil { + t.Fatal(err) + } + if len(zr.File) != 1 || zr.File[0].Name != "file.txt" { + t.Errorf("zip entries = %v", zr.File) + } +} + +func TestGetArchiveNotModified(t *testing.T) { + router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), streamBody: "hello"}) + + req := httptest.NewRequest(http.MethodGet, "/repositories/7/archive?ref=main", nil) + req.Header.Set("If-None-Match", `W/"`+testSHA+`-zip"`) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + if rec.Code != http.StatusNotModified { + t.Fatalf("status = %d", rec.Code) + } + if rec.Body.Len() != 0 { + t.Errorf("304 must have no body, got %d bytes", rec.Body.Len()) + } +} + +func TestGetArchiveErrors(t *testing.T) { + cases := []struct { + name string + target string + prepareErr error + streamErr error + wantStatus int + wantCode string + }{ + {"bad id", "/repositories/abc/archive", nil, nil, http.StatusBadRequest, "invalid_request"}, + {"bad lfs param", "/repositories/7/archive?lfs=maybe", nil, nil, http.StatusBadRequest, "invalid_request"}, + {"repo not found", "/repositories/7/archive", reposervice.ErrRepositoryNotFound, nil, http.StatusNotFound, "repository_not_found"}, + {"ref not found", "/repositories/7/archive?ref=nope", reposervice.ErrRefNotFound, nil, http.StatusNotFound, "ref_not_found"}, + {"invalid ref", "/repositories/7/archive?ref=--x", reposervice.ErrInvalidRef, nil, http.StatusBadRequest, "invalid_request"}, + {"bad format", "/repositories/7/archive?format=rar", reposervice.ErrUnsupportedFormat, nil, http.StatusBadRequest, "invalid_request"}, + {"lfs disabled", "/repositories/7/archive?lfs=true", reposervice.ErrLFSNotEnabled, nil, http.StatusBadRequest, "invalid_request"}, + {"stream fails before first byte", "/repositories/7/archive", nil, io.ErrUnexpectedEOF, http.StatusInternalServerError, "internal_error"}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), prepareErr: tc.prepareErr, streamErr: tc.streamErr}) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, tc.target, nil)) + + if rec.Code != tc.wantStatus { + t.Fatalf("status = %d, want %d: %s", rec.Code, tc.wantStatus, rec.Body.String()) + } + var body struct { + Error struct { + Code string `json:"code"` + } `json:"error"` + } + if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { + t.Fatal(err) + } + if body.Error.Code != tc.wantCode { + t.Errorf("code = %q, want %q", body.Error.Code, tc.wantCode) + } + if got := rec.Header().Get("Content-Disposition"); got != "" { + t.Errorf("error response leaked Content-Disposition %q", got) + } + }) + } +} diff --git a/internal/server/control/repositories/handlers.go b/internal/server/control/repositories/handlers.go index c7a6709..588bdf1 100644 --- a/internal/server/control/repositories/handlers.go +++ b/internal/server/control/repositories/handlers.go @@ -2,6 +2,7 @@ package repositories import ( "context" + "io" "github.com/Axenos-dev/HeadlessGit/internal/domain" "github.com/Axenos-dev/HeadlessGit/internal/server/response" @@ -16,6 +17,8 @@ type RepositoryManager interface { SetVisibility(ctx context.Context, repositoryID int64, visibility domain.RepoVisibility) (domain.Repository, error) ListByOwner(ctx context.Context, ownerID int64) ([]domain.Repository, error) Contents(ctx context.Context, repositoryID int64, ref, treePath string) (domain.RepositoryContents, error) + PrepareArchive(ctx context.Context, repositoryID int64, ref, format string, includeLFS bool) (domain.ArchiveRequest, error) + StreamArchive(ctx context.Context, req domain.ArchiveRequest, out io.Writer) error } type handlers struct { @@ -35,6 +38,7 @@ func (h *handlers) RegisterRoutes(parent chi.Router) { r.Post("/", response.Handler(h.logger, h.createRepository)) r.Get("/{repositoryID}", response.Handler(h.logger, h.getRepository)) r.Get("/{repositoryID}/contents", response.Handler(h.logger, h.getContents)) + r.Get("/{repositoryID}/archive", response.Handler(h.logger, h.getArchive)) r.Put("/{repositoryID}/visibility", response.Handler(h.logger, h.setVisibility)) r.Delete("/{repositoryID}", response.Handler(h.logger, h.deleteRepository)) }) diff --git a/internal/server/control/repositories/handlers_test.go b/internal/server/control/repositories/handlers_test.go new file mode 100644 index 0000000..83af4aa --- /dev/null +++ b/internal/server/control/repositories/handlers_test.go @@ -0,0 +1,52 @@ +package repositories + +import ( + "archive/zip" + "context" + "io" + "net/http" + + "github.com/Axenos-dev/HeadlessGit/internal/domain" + "github.com/go-chi/chi/v5" + "go.uber.org/zap" +) + +const testSHA = "aaaabbbbccccddddeeeeffff0000111122223333" + +// fakeManager stubs RepositoryManager for handler tests: embed the interface +// and override only what the endpoint under test touches +type fakeManager struct { + RepositoryManager + prepareReq domain.ArchiveRequest + prepareErr error + streamBody string + streamErr error +} + +func (f fakeManager) PrepareArchive(ctx context.Context, repositoryID int64, ref, format string, includeLFS bool) (domain.ArchiveRequest, error) { + return f.prepareReq, f.prepareErr +} + +func (f fakeManager) StreamArchive(ctx context.Context, req domain.ArchiveRequest, out io.Writer) error { + if f.streamBody != "" { + zw := zip.NewWriter(out) + w, err := zw.Create("file.txt") + if err != nil { + return err + } + if _, err := w.Write([]byte(f.streamBody)); err != nil { + return err + } + if err := zw.Close(); err != nil { + return err + } + } + return f.streamErr +} + +// newTestRouter mounts the handlers the same way the control server does +func newTestRouter(svc RepositoryManager) http.Handler { + r := chi.NewRouter() + NewHandlers(zap.NewNop(), svc).RegisterRoutes(r) + return r +} diff --git a/internal/server/git/githttp/e2e_test.go b/internal/server/git/githttp/e2e_test.go index f535af6..754fbba 100644 --- a/internal/server/git/githttp/e2e_test.go +++ b/internal/server/git/githttp/e2e_test.go @@ -45,7 +45,7 @@ func TestGitHTTPEndToEnd(t *testing.T) { t.Fatal(err) } - repoSvc := repositories.NewService(log, repositories.NewRegistry(database), backend) + repoSvc := repositories.NewService(log, repositories.NewRegistry(database), backend, nil) authSvc := auth.NewService(log, auth.NewRegistry(database)) permsSvc := permissions.NewService(permissions.NewRegistry(database)) usersSvc := users.NewService(users.NewRegistry(database)) diff --git a/internal/server/git/githttp/lfs_e2e_test.go b/internal/server/git/githttp/lfs_e2e_test.go index 7b0fc27..cf0b17e 100644 --- a/internal/server/git/githttp/lfs_e2e_test.go +++ b/internal/server/git/githttp/lfs_e2e_test.go @@ -63,7 +63,7 @@ func TestGitLFSEndToEnd(t *testing.T) { t.Fatal(err) } - repoSvc := repositories.NewService(log, repositories.NewRegistry(database), backend) + repoSvc := repositories.NewService(log, repositories.NewRegistry(database), backend, nil) authSvc := auth.NewService(log, auth.NewRegistry(database)) permsSvc := permissions.NewService(permissions.NewRegistry(database)) usersSvc := users.NewService(users.NewRegistry(database)) diff --git a/internal/services/repositories/archive_test.go b/internal/services/repositories/archive_test.go new file mode 100644 index 0000000..8adc36b --- /dev/null +++ b/internal/services/repositories/archive_test.go @@ -0,0 +1,172 @@ +package repositories + +import ( + "archive/tar" + "archive/zip" + "bytes" + "context" + "database/sql" + "errors" + "fmt" + "io" + "strings" + "testing" + + "github.com/Axenos-dev/HeadlessGit/internal/db/gen" + "github.com/Axenos-dev/HeadlessGit/internal/domain" + "github.com/Axenos-dev/HeadlessGit/internal/gitbackend" + "go.uber.org/zap" +) + +const testSHA = "aaaabbbbccccddddeeeeffff0000111122223333" + +type fakeRegistry struct { + Registry + repo gen.Repository + err error +} + +func (f fakeRegistry) GetRepository(ctx context.Context, repositoryID int64) (gen.Repository, error) { + return f.repo, f.err +} + +type fakeStorage struct { + RepositoryStorage + sha string + resolveErr error + tarBytes []byte +} + +func (f fakeStorage) ResolveCommit(ctx context.Context, storagePath, rev string) (string, error) { + if f.resolveErr != nil { + return "", f.resolveErr + } + return f.sha, nil +} + +func (f fakeStorage) ArchiveTar(ctx context.Context, storagePath, rev string, out io.Writer) (string, error) { + if _, err := out.Write(f.tarBytes); err != nil { + return "", err + } + return f.sha, nil +} + +type fakeLFS struct { + objects map[string]string // oid -> content +} + +func (f fakeLFS) GetObject(ctx context.Context, repo domain.Repository, oid string) (io.ReadCloser, int64, error) { + content, ok := f.objects[oid] + if !ok { + return nil, 0, errors.New("object not found") + } + return io.NopCloser(strings.NewReader(content)), int64(len(content)), nil +} + +func TestPrepareArchive(t *testing.T) { + row := gen.Repository{ID: 7, RepositoryName: "myrepo", StoragePath: "7/myrepo.git", Visibility: "private"} + + cases := []struct { + name string + registry Registry + storage RepositoryStorage + lfs LFSObjects + format string + includeLFS bool + wantErr error + }{ + {"unsupported format", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, nil, "rar", false, ErrUnsupportedFormat}, + {"lfs disabled", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, nil, "zip", true, ErrLFSNotEnabled}, + {"lfs enabled ok", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, fakeLFS{}, "zip", true, nil}, + {"repo not found", fakeRegistry{err: sql.ErrNoRows}, fakeStorage{sha: testSHA}, nil, "zip", false, ErrRepositoryNotFound}, + {"invalid ref", fakeRegistry{repo: row}, fakeStorage{resolveErr: gitbackend.ErrInvalidRev}, nil, "zip", false, ErrInvalidRef}, + {"ref not found", fakeRegistry{repo: row}, fakeStorage{resolveErr: gitbackend.ErrRevNotFound}, nil, "zip", false, ErrRefNotFound}, + {"ok", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, nil, "zip", false, nil}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + svc := NewService(zap.NewNop(), tc.registry, tc.storage, tc.lfs) + req, err := svc.PrepareArchive(context.Background(), row.ID, "main", tc.format, tc.includeLFS) + if !errors.Is(err, tc.wantErr) { + t.Fatalf("PrepareArchive error = %v, want %v", err, tc.wantErr) + } + if tc.wantErr == nil { + if req.CommitSHA != testSHA || req.Repository.ID != row.ID || req.Format != domain.ArchiveFormatZip { + t.Errorf("PrepareArchive = %+v", req) + } + if want := "myrepo-aaaabbbbcccc.zip"; req.Filename() != want { + t.Errorf("Filename = %q, want %q", req.Filename(), want) + } + } + }) + } +} + +func TestStreamArchiveSmudgesLFS(t *testing.T) { + oid := strings.Repeat("ab", 32) + content := "REAL LFS CONTENT" + pointer := fmt.Sprintf("version https://git-lfs.github.com/spec/v1\noid sha256:%s\nsize %d\n", oid, len(content)) + + var tarBuf bytes.Buffer + tw := tar.NewWriter(&tarBuf) + for _, e := range []struct{ name, body string }{ + {"README.md", "hello\n"}, + {"big.bin", pointer}, + } { + if err := tw.WriteHeader(&tar.Header{Typeflag: tar.TypeReg, Name: e.name, Mode: 0o644, Size: int64(len(e.body))}); err != nil { + t.Fatal(err) + } + if _, err := tw.Write([]byte(e.body)); err != nil { + t.Fatal(err) + } + } + if err := tw.Close(); err != nil { + t.Fatal(err) + } + + svc := NewService( + zap.NewNop(), + fakeRegistry{}, + fakeStorage{sha: testSHA, tarBytes: tarBuf.Bytes()}, + fakeLFS{objects: map[string]string{oid: content}}, + ) + + req := domain.ArchiveRequest{ + Repository: domain.Repository{ID: 7, RepositoryName: "myrepo", StoragePath: "7/myrepo.git"}, + CommitSHA: testSHA, + Format: domain.ArchiveFormatZip, + IncludeLFS: true, + } + + var out bytes.Buffer + if err := svc.StreamArchive(context.Background(), req, &out); err != nil { + t.Fatal(err) + } + + zr, err := zip.NewReader(bytes.NewReader(out.Bytes()), int64(out.Len())) + if err != nil { + t.Fatal(err) + } + got := map[string]string{} + for _, f := range zr.File { + rc, err := f.Open() + if err != nil { + t.Fatal(err) + } + body, err := io.ReadAll(rc) + rc.Close() + if err != nil { + t.Fatal(err) + } + got[f.Name] = string(body) + } + + prefix := "myrepo-aaaabbbbcccc/" + if got[prefix+"big.bin"] != content { + t.Errorf("big.bin not smudged: %q", got[prefix+"big.bin"]) + } + if got[prefix+"README.md"] != "hello\n" { + t.Errorf("README.md = %q", got[prefix+"README.md"]) + } +} diff --git a/internal/services/repositories/errors.go b/internal/services/repositories/errors.go index d1f03d7..cf129f2 100644 --- a/internal/services/repositories/errors.go +++ b/internal/services/repositories/errors.go @@ -11,4 +11,7 @@ var ( ErrPathNotFound = errors.New("path not found") ErrInvalidRef = errors.New("invalid ref") ErrInvalidPath = errors.New("invalid path") + + ErrUnsupportedFormat = errors.New("unsupported archive format") + ErrLFSNotEnabled = errors.New("lfs is not enabled") ) diff --git a/internal/services/repositories/service.go b/internal/services/repositories/service.go index 578d30e..27ec4d5 100644 --- a/internal/services/repositories/service.go +++ b/internal/services/repositories/service.go @@ -5,10 +5,12 @@ import ( "database/sql" "errors" "fmt" + "io" "path" "strings" "time" + "github.com/Axenos-dev/HeadlessGit/internal/archive" "github.com/Axenos-dev/HeadlessGit/internal/db/gen" "github.com/Axenos-dev/HeadlessGit/internal/domain" "github.com/Axenos-dev/HeadlessGit/internal/gitbackend" @@ -28,19 +30,27 @@ type RepositoryStorage interface { InitBare(ctx context.Context, storagePath string) error Remove(ctx context.Context, storagePath string) error ListTree(ctx context.Context, storagePath, rev, treePath string) (gitbackend.TreeListing, error) + ResolveCommit(ctx context.Context, storagePath, rev string) (string, error) + ArchiveTar(ctx context.Context, storagePath, rev string, out io.Writer) (string, error) +} + +type LFSObjects interface { + GetObject(ctx context.Context, repo domain.Repository, oid string) (io.ReadCloser, int64, error) } type Service struct { logger *zap.Logger registry Registry storage RepositoryStorage + lfs LFSObjects } -func NewService(logger *zap.Logger, registry Registry, storage RepositoryStorage) *Service { +func NewService(logger *zap.Logger, registry Registry, storage RepositoryStorage, lfs LFSObjects) *Service { return &Service{ logger: logger, registry: registry, storage: storage, + lfs: lfs, } } @@ -182,6 +192,78 @@ func (s *Service) GetRepositoryByPath(ctx context.Context, namespace, name strin return toDomain(repo), nil } +func (s *Service) PrepareArchive(ctx context.Context, repositoryID int64, ref, format string, includeLFS bool) (domain.ArchiveRequest, error) { + f, ok := domain.ParseArchiveFormat(format) + if !ok { + return domain.ArchiveRequest{}, ErrUnsupportedFormat + } + if includeLFS && s.lfs == nil { + return domain.ArchiveRequest{}, ErrLFSNotEnabled + } + + repo, err := s.Get(ctx, repositoryID) + if err != nil { + return domain.ArchiveRequest{}, err + } + + sha, err := s.storage.ResolveCommit(ctx, repo.StoragePath, ref) + switch { + case errors.Is(err, gitbackend.ErrInvalidRev): + return domain.ArchiveRequest{}, ErrInvalidRef + case errors.Is(err, gitbackend.ErrRevNotFound): + return domain.ArchiveRequest{}, ErrRefNotFound + case err != nil: + return domain.ArchiveRequest{}, err + } + + return domain.ArchiveRequest{ + Repository: repo, + CommitSHA: sha, + Format: f, + IncludeLFS: includeLFS, + }, nil +} + +func (s *Service) StreamArchive(ctx context.Context, req domain.ArchiveRequest, out io.Writer) error { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // create pipe and stream git archive to writer + pr, pw := io.Pipe() + go func() { + _, err := s.storage.ArchiveTar(ctx, req.Repository.StoragePath, req.CommitSHA, pw) + pw.CloseWithError(err) + }() + + // create archive endocer depending on the archive type, connect it to output writer + var enc archive.Encoder + if req.Format == domain.ArchiveFormatTarGz { + enc = archive.NewTarGzEncoder(out) + } else { + enc = archive.NewZipEncoder(out) + } + + // define a spefic smudge function for LFS objects + // to translate LFS pointers into a real blobs + var smudge archive.SmudgeFunc + if req.IncludeLFS { + smudge = func(oid string) (io.ReadCloser, int64, error) { + rc, size, err := s.lfs.GetObject(ctx, req.Repository, oid) + if err != nil { + s.logger.Warn("lfs object unavailable for archive, keeping pointer", + zap.Int64("repository_id", req.Repository.ID), + zap.String("oid", oid), + zap.Error(err), + ) + } + return rc, size, err + } + } + + prefix := fmt.Sprintf("%s-%s/", req.Repository.RepositoryName, domain.ShortSHA(req.CommitSHA)) + return archive.Transform(pr, prefix, smudge, enc) +} + func toDomain(r gen.Repository) domain.Repository { repo := domain.Repository{ ID: r.ID, From 0503b5c9afebb878ceaa6f954b083990c3068497 Mon Sep 17 00:00:00 2001 From: Axenos-dev Date: Sun, 5 Jul 2026 17:15:14 -0700 Subject: [PATCH 3/7] Get blob endpoint --- AGENTS.md | 8 +- internal/archive/pointer.go | 57 ---- internal/archive/transform.go | 8 +- internal/archive/transform_test.go | 32 -- internal/domain/blob.go | 10 + internal/domain/lfs.go | 51 ++- internal/domain/lfs_test.go | 39 +++ internal/gitbackend/backend.go | 2 + internal/gitbackend/errors.go | 11 + internal/gitbackend/local.go | 85 +++++ internal/gitbackend/local_test.go | 75 +++++ internal/gitbackend/types.go | 15 +- .../control/repositories/archive_test.go | 116 ------- internal/server/control/repositories/blob.go | 98 ++++++ .../server/control/repositories/handlers.go | 3 + .../control/repositories/handlers_test.go | 241 ++++++++++++++ internal/server/response/codes.go | 1 + .../services/repositories/archive_test.go | 172 ---------- internal/services/repositories/errors.go | 3 + internal/services/repositories/service.go | 76 +++++ .../services/repositories/service_test.go | 312 ++++++++++++++++++ 21 files changed, 1024 insertions(+), 391 deletions(-) delete mode 100644 internal/archive/pointer.go create mode 100644 internal/domain/blob.go create mode 100644 internal/domain/lfs_test.go create mode 100644 internal/gitbackend/errors.go delete mode 100644 internal/server/control/repositories/archive_test.go create mode 100644 internal/server/control/repositories/blob.go delete mode 100644 internal/services/repositories/archive_test.go create mode 100644 internal/services/repositories/service_test.go diff --git a/AGENTS.md b/AGENTS.md index 3cf9cd7..424173c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -54,7 +54,7 @@ Package map: | `internal/domain` | Core types (repository, account, role, token, ssh key, lfs). | | `internal/services/*` | Business logic per area (repositories, users, auth, permissions, lfs); each has a service + a registry over `db`. | | `internal/storage` | LFS object storage behind an interface (`disk`, `s3`). | -| `internal/archive` | Pure mechanism, no service deps: streaming tar re-encode to zip/tar.gz with an injected LFS smudge callback. | +| `internal/archive` | Pure mechanism: streaming tar re-encode to zip/tar.gz with an injected LFS smudge callback. | | `internal/gitbackend` | Git subprocesses behind a small interface: pack protocol plus read ops (ls-tree, rev resolution, tar archive). | | `internal/server` | Composition root: wires control + git servers, runs and shuts down listeners. | | `internal/server/control` | Control API (REST); sub-handlers in `repositories/`, `users/`, `permissions/`. | @@ -116,6 +116,12 @@ Prefer simple Go: small interfaces at module boundaries, context-aware I/O, expl errors with context, table-driven tests, standard library first. Avoid large global state, framework-heavy abstractions, and dependencies added for small tasks. +**File layout.** Do not multiply files or packages. A service is `service.go` + +`errors.go` + `registry.go` — new service methods go into `service.go`, not new +files. One test file per package where practical (`service_test.go`, +`handlers_test.go`). Small parsing/vocabulary helpers (formats, pointers, modes) +belong in `domain` next to the types they produce, not in new packages. + **Dependencies & interfaces.** The package that _invokes_ a dependency defines a minimal consumer interface for it (e.g. `gitssh`'s `Authenticator`/`TokenMinter`, the handler packages' own interfaces). Composition/router layers (`server`, `git`, diff --git a/internal/archive/pointer.go b/internal/archive/pointer.go deleted file mode 100644 index 37725d4..0000000 --- a/internal/archive/pointer.go +++ /dev/null @@ -1,57 +0,0 @@ -package archive - -import ( - "strconv" - "strings" -) - -// pointer file is a small key-value text blob -// and it cant be bigger than this -const lfsPointerMaxSize = 1024 -const lfsVersionLine = "version https://git-lfs.github.com/spec/v1" - -type lfsPointer struct { - oid string - size int64 -} - -func parseLFSPointer(data []byte) (lfsPointer, bool) { - if len(data) == 0 || len(data) > lfsPointerMaxSize { - return lfsPointer{}, false - } - - lines := strings.Split(strings.TrimSuffix(string(data), "\n"), "\n") - if len(lines) < 3 || lines[0] != lfsVersionLine { - return lfsPointer{}, false - } - - ptr := lfsPointer{size: -1} - for _, line := range lines[1:] { - if oid, ok := strings.CutPrefix(line, "oid sha256:"); ok { - ptr.oid = oid - } else if raw, ok := strings.CutPrefix(line, "size "); ok { - n, err := strconv.ParseInt(raw, 10, 64) - if err != nil { - return lfsPointer{}, false - } - ptr.size = n - } - } - - if !validOID(ptr.oid) || ptr.size < 0 { - return lfsPointer{}, false - } - return ptr, true -} - -func validOID(oid string) bool { - if len(oid) != 64 { - return false - } - for _, c := range oid { - if (c < '0' || c > '9') && (c < 'a' || c > 'f') { - return false - } - } - return true -} diff --git a/internal/archive/transform.go b/internal/archive/transform.go index 9c3ff80..0b3421e 100644 --- a/internal/archive/transform.go +++ b/internal/archive/transform.go @@ -4,6 +4,8 @@ import ( "archive/tar" "bytes" "io" + + "github.com/Axenos-dev/HeadlessGit/internal/domain" ) type SmudgeFunc func(oid string) (io.ReadCloser, int64, error) @@ -33,7 +35,7 @@ func Transform(src io.Reader, prefix string, smudge SmudgeFunc, enc Encoder) err func writeEntry(enc Encoder, hdr *tar.Header, body io.Reader, smudge SmudgeFunc) error { // only small regular files can be LFS pointers, everything else passes through - if smudge == nil || hdr.Typeflag != tar.TypeReg || hdr.Size > lfsPointerMaxSize { + if smudge == nil || hdr.Typeflag != tar.TypeReg || hdr.Size > domain.LFSPointerMaxSize { return enc.Write(hdr, body) } @@ -41,12 +43,12 @@ func writeEntry(enc Encoder, hdr *tar.Header, body io.Reader, smudge SmudgeFunc) if err != nil { return err } - ptr, ok := parseLFSPointer(data) + ptr, ok := domain.ParseLFSPointer(data) if !ok { return enc.Write(hdr, bytes.NewReader(data)) } - rc, size, err := smudge(ptr.oid) + rc, size, err := smudge(ptr.OID) if err != nil { // missing or foreign object: keep the pointer bytes, never fail the archive return enc.Write(hdr, bytes.NewReader(data)) diff --git a/internal/archive/transform_test.go b/internal/archive/transform_test.go index b6dae30..4d567f6 100644 --- a/internal/archive/transform_test.go +++ b/internal/archive/transform_test.go @@ -12,38 +12,6 @@ import ( "testing" ) -func TestParseLFSPointer(t *testing.T) { - oid := strings.Repeat("ab", 32) - valid := "version https://git-lfs.github.com/spec/v1\noid sha256:" + oid + "\nsize 12345\n" - - cases := []struct { - name string - data string - ok bool - }{ - {"valid", valid, true}, - {"empty", "", false}, - {"plain text", "hello world\nthis mentions oid sha256: things\nsize 5\n", false}, - {"wrong version", "version https://example.com/spec/v1\noid sha256:" + oid + "\nsize 5\n", false}, - {"short oid", "version https://git-lfs.github.com/spec/v1\noid sha256:abcd\nsize 5\n", false}, - {"missing size", "version https://git-lfs.github.com/spec/v1\noid sha256:" + oid + "\n\n", false}, - {"bad size", "version https://git-lfs.github.com/spec/v1\noid sha256:" + oid + "\nsize lots\n", false}, - {"oversized", valid + strings.Repeat("x", lfsPointerMaxSize), false}, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - ptr, ok := parseLFSPointer([]byte(tc.data)) - if ok != tc.ok { - t.Fatalf("parseLFSPointer ok = %v, want %v", ok, tc.ok) - } - if ok && (ptr.oid != oid || ptr.size != 12345) { - t.Errorf("parseLFSPointer = %+v", ptr) - } - }) - } -} - // builds a tar the way git archive would emit it: pax global header first, // then dirs, files (including an LFS pointer), and a symlink func buildTestTar(t *testing.T, pointer string) []byte { diff --git a/internal/domain/blob.go b/internal/domain/blob.go new file mode 100644 index 0000000..d5e4542 --- /dev/null +++ b/internal/domain/blob.go @@ -0,0 +1,10 @@ +package domain + +type BlobRequest struct { + Repository Repository + CommitSHA string + BlobSHA string + Path string + Size int64 // exact byte count of what will be streamed + LFSOID string // non-empty when the blob is an LFS pointer being smudged +} diff --git a/internal/domain/lfs.go b/internal/domain/lfs.go index fed516b..ccf8f49 100644 --- a/internal/domain/lfs.go +++ b/internal/domain/lfs.go @@ -1,6 +1,10 @@ package domain -import "time" +import ( + "strconv" + "strings" + "time" +) type LFSOperation string @@ -9,6 +13,9 @@ const ( LFSOperationDownload LFSOperation = "download" ) +const LFSPointerMaxSize = 1024 +const lfsVersionLine = "version https://git-lfs.github.com/spec/v1" + type LFSPointer struct { OID string Size int64 @@ -31,3 +38,45 @@ type LFSObjectResponse struct { Actions map[string]LFSAction Error *LFSObjectError } + +func ParseLFSPointer(data []byte) (LFSPointer, bool) { + if len(data) == 0 || len(data) > LFSPointerMaxSize { + return LFSPointer{}, false + } + + lines := strings.Split(strings.TrimSuffix(string(data), "\n"), "\n") + if len(lines) < 3 || lines[0] != lfsVersionLine { + return LFSPointer{}, false + } + + ptr := LFSPointer{Size: -1} + for _, line := range lines[1:] { + if oid, ok := strings.CutPrefix(line, "oid sha256:"); ok { + ptr.OID = oid + } else if raw, ok := strings.CutPrefix(line, "size "); ok { + n, err := strconv.ParseInt(raw, 10, 64) + if err != nil { + return LFSPointer{}, false + } + ptr.Size = n + } + } + + if !validLFSOID(ptr.OID) || ptr.Size < 0 { + return LFSPointer{}, false + } + return ptr, true +} + +// enforces a 64 char lowercase hex sha256 +func validLFSOID(oid string) bool { + if len(oid) != 64 { + return false + } + for _, c := range oid { + if (c < '0' || c > '9') && (c < 'a' || c > 'f') { + return false + } + } + return true +} diff --git a/internal/domain/lfs_test.go b/internal/domain/lfs_test.go new file mode 100644 index 0000000..ae0d8b6 --- /dev/null +++ b/internal/domain/lfs_test.go @@ -0,0 +1,39 @@ +package domain + +import ( + "strings" + "testing" +) + +func TestParseLFSPointer(t *testing.T) { + oid := strings.Repeat("ab", 32) + valid := "version https://git-lfs.github.com/spec/v1\noid sha256:" + oid + "\nsize 12345\n" + + cases := []struct { + name string + data string + ok bool + }{ + {"valid", valid, true}, + {"empty", "", false}, + {"plain text", "hello world\nthis mentions oid sha256: things\nsize 5\n", false}, + {"wrong version", "version https://example.com/spec/v1\noid sha256:" + oid + "\nsize 5\n", false}, + {"short oid", "version https://git-lfs.github.com/spec/v1\noid sha256:abcd\nsize 5\n", false}, + {"uppercase oid", "version https://git-lfs.github.com/spec/v1\noid sha256:" + strings.ToUpper(oid) + "\nsize 5\n", false}, + {"missing size", "version https://git-lfs.github.com/spec/v1\noid sha256:" + oid + "\n\n", false}, + {"bad size", "version https://git-lfs.github.com/spec/v1\noid sha256:" + oid + "\nsize lots\n", false}, + {"oversized", valid + strings.Repeat("x", LFSPointerMaxSize), false}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ptr, ok := ParseLFSPointer([]byte(tc.data)) + if ok != tc.ok { + t.Fatalf("ParseLFSPointer ok = %v, want %v", ok, tc.ok) + } + if ok && (ptr.OID != oid || ptr.Size != 12345) { + t.Errorf("ParseLFSPointer = %+v", ptr) + } + }) + } +} diff --git a/internal/gitbackend/backend.go b/internal/gitbackend/backend.go index ff98705..844c549 100644 --- a/internal/gitbackend/backend.go +++ b/internal/gitbackend/backend.go @@ -15,4 +15,6 @@ type Backend interface { ListTree(ctx context.Context, storagePath, rev, treePath string) (TreeListing, error) ResolveCommit(ctx context.Context, storagePath, rev string) (string, error) ArchiveTar(ctx context.Context, storagePath, rev string, out io.Writer) (string, error) + StatBlob(ctx context.Context, storagePath, rev, treePath string) (BlobInfo, error) + ReadBlob(ctx context.Context, storagePath, blobSHA string, out io.Writer) error } diff --git a/internal/gitbackend/errors.go b/internal/gitbackend/errors.go new file mode 100644 index 0000000..ec83f9f --- /dev/null +++ b/internal/gitbackend/errors.go @@ -0,0 +1,11 @@ +package gitbackend + +import "errors" + +var ( + ErrInvalidRev = errors.New("invalid revision") + ErrInvalidPath = errors.New("invalid tree path") + ErrRevNotFound = errors.New("revision not found") + ErrPathNotFound = errors.New("path not found in tree") + ErrNotABlob = errors.New("path is not a blob") +) diff --git a/internal/gitbackend/local.go b/internal/gitbackend/local.go index 2520c7b..b094bbd 100644 --- a/internal/gitbackend/local.go +++ b/internal/gitbackend/local.go @@ -264,6 +264,79 @@ func (l *Local) ArchiveTar(ctx context.Context, storagePath, rev string, out io. return commitSHA, nil } +func (l *Local) StatBlob(ctx context.Context, storagePath, rev, treePath string) (BlobInfo, error) { + dir, err := l.resolve(storagePath) + if err != nil { + return BlobInfo{}, err + } + + treePath, err = normalizeTreePath(treePath) + if err != nil { + return BlobInfo{}, err + } + if treePath == "" { + // the root is a tree by definition (and its not a blob) + return BlobInfo{}, fmt.Errorf("%w: %q", ErrNotABlob, treePath) + } + + commitSHA, err := l.ResolveCommit(ctx, storagePath, rev) + if err != nil { + return BlobInfo{}, err + } + + ctx, cancel := context.WithTimeout(ctx, l.timeout) + defer cancel() + + blobSHA, err := l.revParse(ctx, dir, commitSHA+":"+treePath) + if err != nil { + return BlobInfo{}, fmt.Errorf("%w: %q", ErrPathNotFound, treePath) + } + + cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "cat-file", "--batch-check") + cmd.Stdin = strings.NewReader(blobSHA + "\n") + var out, stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return BlobInfo{}, fmt.Errorf("cat-file --batch-check: %w: %s", err, strings.TrimSpace(stderr.String())) + } + + // output shape: " " + fields := strings.Fields(out.String()) + if len(fields) != 3 { + return BlobInfo{}, fmt.Errorf("malformed batch-check output: %q", out.String()) + } + if fields[1] != "blob" { + return BlobInfo{}, fmt.Errorf("%w: %q is a %s", ErrNotABlob, treePath, fields[1]) + } + size, err := strconv.ParseInt(fields[2], 10, 64) + if err != nil { + return BlobInfo{}, fmt.Errorf("malformed blob size %q: %w", fields[2], err) + } + + return BlobInfo{CommitSHA: commitSHA, BlobSHA: blobSHA, Size: size}, nil +} + +func (l *Local) ReadBlob(ctx context.Context, storagePath, blobSHA string, out io.Writer) error { + dir, err := l.resolve(storagePath) + if err != nil { + return err + } + + if !isHexSHA(blobSHA) { + return fmt.Errorf("%w: %q", ErrInvalidRev, blobSHA) + } + + cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "cat-file", "blob", blobSHA) + cmd.Stdout = out + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return fmt.Errorf("cat-file blob: %w: %s", err, strings.TrimSpace(stderr.String())) + } + return nil +} + func (l *Local) ResolveCommit(ctx context.Context, storagePath, rev string) (string, error) { dir, err := l.resolve(storagePath) if err != nil { @@ -412,3 +485,15 @@ func (l *Local) resolve(storagePath string) (string, error) { } return full, nil } + +func isHexSHA(s string) bool { + if len(s) != 40 { + return false + } + for _, c := range s { + if (c < '0' || c > '9') && (c < 'a' || c > 'f') { + return false + } + } + return true +} diff --git a/internal/gitbackend/local_test.go b/internal/gitbackend/local_test.go index 0031f38..55012ac 100644 --- a/internal/gitbackend/local_test.go +++ b/internal/gitbackend/local_test.go @@ -358,6 +358,81 @@ func TestArchiveTar(t *testing.T) { } } +func TestBlob(t *testing.T) { + if _, err := exec.LookPath("git"); err != nil { + t.Skip("git not on PATH") + } + + root := t.TempDir() + l, err := NewLocal(root) + if err != nil { + t.Fatal(err) + } + ctx := context.Background() + + if err := l.InitBare(ctx, "1/test.git"); err != nil { + t.Fatal(err) + } + + wt := filepath.Join(t.TempDir(), "wt") + gitRun(t, ".", "clone", filepath.Join(root, "1/test.git"), wt) + if err := os.MkdirAll(filepath.Join(wt, "src"), 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(wt, "src", "main.go"), []byte("package main\n"), 0o644); err != nil { + t.Fatal(err) + } + gitRun(t, wt, "add", "-A") + gitRun(t, wt, "commit", "-m", "init") + gitRun(t, wt, "push", "origin", "HEAD:refs/heads/main") + + info, err := l.StatBlob(ctx, "1/test.git", "main", "src/main.go") + if err != nil { + t.Fatal(err) + } + if info.Size != int64(len("package main\n")) { + t.Errorf("size = %d", info.Size) + } + if !isHexSHA(info.CommitSHA) || !isHexSHA(info.BlobSHA) { + t.Errorf("shas not resolved: %+v", info) + } + + var buf bytes.Buffer + if err := l.ReadBlob(ctx, "1/test.git", info.BlobSHA, &buf); err != nil { + t.Fatal(err) + } + if buf.String() != "package main\n" { + t.Errorf("content = %q", buf.String()) + } + + t.Run("errors", func(t *testing.T) { + cases := []struct { + name, rev, path string + want error + }{ + {"root is a tree", "main", "", ErrNotABlob}, + {"dir is a tree", "main", "src", ErrNotABlob}, + {"missing path", "main", "nope.txt", ErrPathNotFound}, + {"unknown rev", "nope", "src/main.go", ErrRevNotFound}, + {"hostile rev", "--help", "src/main.go", ErrInvalidRev}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if _, err := l.StatBlob(ctx, "1/test.git", tc.rev, tc.path); !errors.Is(err, tc.want) { + t.Errorf("StatBlob(%q, %q) = %v, want %v", tc.rev, tc.path, err, tc.want) + } + }) + } + + // ReadBlob refuses anything that is not a plain object id + for _, sha := range []string{"main", "--help", "HEAD", strings.Repeat("a", 39), strings.Repeat("A", 40)} { + if err := l.ReadBlob(ctx, "1/test.git", sha, io.Discard); !errors.Is(err, ErrInvalidRev) { + t.Errorf("ReadBlob(%q) = %v, want ErrInvalidRev", sha, err) + } + } + }) +} + func TestDiffRefs(t *testing.T) { cases := []struct { name string diff --git a/internal/gitbackend/types.go b/internal/gitbackend/types.go index ed9d136..5bb6e8b 100644 --- a/internal/gitbackend/types.go +++ b/internal/gitbackend/types.go @@ -1,7 +1,5 @@ package gitbackend -import "errors" - // the all-zero object id git uses to denote a missing ref // its zero in before, if it was created after // or its zero after, if it was deleted before @@ -10,13 +8,6 @@ const zeroSHA = "0000000000000000000000000000000000000000" // hard cap on entries returned per directory level const maxTreeEntries = 10_000 -var ( - ErrInvalidRev = errors.New("invalid revision") - ErrInvalidPath = errors.New("invalid tree path") - ErrRevNotFound = errors.New("revision not found") - ErrPathNotFound = errors.New("path not found in tree") -) - type RefChange struct { Ref string OldSHA string @@ -36,3 +27,9 @@ type TreeListing struct { Entries []TreeEntry Truncated bool } + +type BlobInfo struct { + CommitSHA string + BlobSHA string + Size int64 +} diff --git a/internal/server/control/repositories/archive_test.go b/internal/server/control/repositories/archive_test.go deleted file mode 100644 index 030b322..0000000 --- a/internal/server/control/repositories/archive_test.go +++ /dev/null @@ -1,116 +0,0 @@ -package repositories - -import ( - "archive/zip" - "bytes" - "encoding/json" - "io" - "net/http" - "net/http/httptest" - "testing" - - "github.com/Axenos-dev/HeadlessGit/internal/domain" - reposervice "github.com/Axenos-dev/HeadlessGit/internal/services/repositories" -) - -func testArchiveRequest() domain.ArchiveRequest { - return domain.ArchiveRequest{ - Repository: domain.Repository{ID: 7, RepositoryName: "myrepo"}, - CommitSHA: testSHA, - Format: domain.ArchiveFormatZip, - } -} - -func TestGetArchive(t *testing.T) { - router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), streamBody: "hello"}) - - rec := httptest.NewRecorder() - router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/repositories/7/archive?ref=main", nil)) - - if rec.Code != http.StatusOK { - t.Fatalf("status = %d, body %s", rec.Code, rec.Body.String()) - } - if got := rec.Header().Get("Content-Type"); got != "application/zip" { - t.Errorf("Content-Type = %q", got) - } - if got := rec.Header().Get("Content-Disposition"); got != `attachment; filename="myrepo-aaaabbbbcccc.zip"` { - t.Errorf("Content-Disposition = %q", got) - } - if got := rec.Header().Get("ETag"); got != `W/"`+testSHA+`-zip"` { - t.Errorf("ETag = %q", got) - } - if got := rec.Header().Get("X-HeadlessGit-Commit"); got != testSHA { - t.Errorf("X-HeadlessGit-Commit = %q", got) - } - - // the body must be a readable zip - zr, err := zip.NewReader(bytes.NewReader(rec.Body.Bytes()), int64(rec.Body.Len())) - if err != nil { - t.Fatal(err) - } - if len(zr.File) != 1 || zr.File[0].Name != "file.txt" { - t.Errorf("zip entries = %v", zr.File) - } -} - -func TestGetArchiveNotModified(t *testing.T) { - router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), streamBody: "hello"}) - - req := httptest.NewRequest(http.MethodGet, "/repositories/7/archive?ref=main", nil) - req.Header.Set("If-None-Match", `W/"`+testSHA+`-zip"`) - rec := httptest.NewRecorder() - router.ServeHTTP(rec, req) - - if rec.Code != http.StatusNotModified { - t.Fatalf("status = %d", rec.Code) - } - if rec.Body.Len() != 0 { - t.Errorf("304 must have no body, got %d bytes", rec.Body.Len()) - } -} - -func TestGetArchiveErrors(t *testing.T) { - cases := []struct { - name string - target string - prepareErr error - streamErr error - wantStatus int - wantCode string - }{ - {"bad id", "/repositories/abc/archive", nil, nil, http.StatusBadRequest, "invalid_request"}, - {"bad lfs param", "/repositories/7/archive?lfs=maybe", nil, nil, http.StatusBadRequest, "invalid_request"}, - {"repo not found", "/repositories/7/archive", reposervice.ErrRepositoryNotFound, nil, http.StatusNotFound, "repository_not_found"}, - {"ref not found", "/repositories/7/archive?ref=nope", reposervice.ErrRefNotFound, nil, http.StatusNotFound, "ref_not_found"}, - {"invalid ref", "/repositories/7/archive?ref=--x", reposervice.ErrInvalidRef, nil, http.StatusBadRequest, "invalid_request"}, - {"bad format", "/repositories/7/archive?format=rar", reposervice.ErrUnsupportedFormat, nil, http.StatusBadRequest, "invalid_request"}, - {"lfs disabled", "/repositories/7/archive?lfs=true", reposervice.ErrLFSNotEnabled, nil, http.StatusBadRequest, "invalid_request"}, - {"stream fails before first byte", "/repositories/7/archive", nil, io.ErrUnexpectedEOF, http.StatusInternalServerError, "internal_error"}, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), prepareErr: tc.prepareErr, streamErr: tc.streamErr}) - rec := httptest.NewRecorder() - router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, tc.target, nil)) - - if rec.Code != tc.wantStatus { - t.Fatalf("status = %d, want %d: %s", rec.Code, tc.wantStatus, rec.Body.String()) - } - var body struct { - Error struct { - Code string `json:"code"` - } `json:"error"` - } - if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { - t.Fatal(err) - } - if body.Error.Code != tc.wantCode { - t.Errorf("code = %q, want %q", body.Error.Code, tc.wantCode) - } - if got := rec.Header().Get("Content-Disposition"); got != "" { - t.Errorf("error response leaked Content-Disposition %q", got) - } - }) - } -} diff --git a/internal/server/control/repositories/blob.go b/internal/server/control/repositories/blob.go new file mode 100644 index 0000000..248434c --- /dev/null +++ b/internal/server/control/repositories/blob.go @@ -0,0 +1,98 @@ +package repositories + +import ( + "errors" + "fmt" + "net/http" + "path" + "strconv" + + "github.com/Axenos-dev/HeadlessGit/internal/domain" + "github.com/Axenos-dev/HeadlessGit/internal/server/response" + reposervice "github.com/Axenos-dev/HeadlessGit/internal/services/repositories" + "github.com/go-chi/chi/v5" + "go.uber.org/zap" +) + +func (h *handlers) getBlob(w http.ResponseWriter, r *http.Request) error { + id, err := strconv.ParseInt(chi.URLParam(r, "repositoryID"), 10, 64) + if err != nil { + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid repository id") + } + + q := r.URL.Query() + includeLFS := false + if raw := q.Get("lfs"); raw != "" { + includeLFS, err = strconv.ParseBool(raw) + if err != nil { + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "lfs must be a boolean") + } + } + + req, err := h.service.PrepareBlob(r.Context(), id, q.Get("ref"), q.Get("path"), includeLFS) + switch { + case errors.Is(err, reposervice.ErrRepositoryNotFound): + return response.NewError(http.StatusNotFound, response.CodeRepositoryNotFound, "repository not found") + case errors.Is(err, reposervice.ErrRefNotFound): + return response.NewError(http.StatusNotFound, response.CodeRefNotFound, "ref not found") + case errors.Is(err, reposervice.ErrPathNotFound): + return response.NewError(http.StatusNotFound, response.CodePathNotFound, "path not found") + case errors.Is(err, reposervice.ErrLFSObjectNotFound): + return response.NewError(http.StatusNotFound, response.CodeLFSObjectNotFound, "lfs object not found") + case errors.Is(err, reposervice.ErrNotAFile): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "path is not a file, use the contents endpoint") + case errors.Is(err, reposervice.ErrInvalidRef): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid ref") + case errors.Is(err, reposervice.ErrInvalidPath): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid path") + case errors.Is(err, reposervice.ErrLFSNotEnabled): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "lfs is not enabled") + case err != nil: + h.logger.Error("failed to prepare blob", zap.Error(err)) + return response.NewError(http.StatusInternalServerError, response.CodeInternalError, "failed to prepare blob") + } + + etag := blobETag(req) + if r.Header.Get("If-None-Match") == etag { + w.Header().Set("ETag", etag) + w.WriteHeader(http.StatusNotModified) + return nil + } + + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Length", strconv.FormatInt(req.Size, 10)) + w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", path.Base(req.Path))) + w.Header().Set("ETag", etag) + w.Header().Set("X-HeadlessGit-Commit", req.CommitSHA) + + cw := &countingWriter{w: w} + if err := h.service.StreamBlob(r.Context(), req, cw); err != nil { + // nothing sent yet + if cw.n == 0 { + // undo the blob headers + w.Header().Del("Content-Type") + w.Header().Del("Content-Length") + w.Header().Del("Content-Disposition") + w.Header().Del("ETag") + w.Header().Del("X-HeadlessGit-Commit") + h.logger.Error("failed to stream blob", zap.Int64("repository_id", id), zap.Error(err)) + // and return normal error + return response.NewError(http.StatusInternalServerError, response.CodeInternalError, "failed to stream blob") + } + + // otherwise just log, the bytes were already streamed + h.logger.Error("blob stream aborted mid-flight", + zap.Int64("repository_id", id), + zap.Int64("bytes_written", cw.n), + zap.Error(err), + ) + } + return nil +} + +func blobETag(req domain.BlobRequest) string { + if req.LFSOID != "" { + return fmt.Sprintf(`"%s-lfs"`, req.BlobSHA) + } + return fmt.Sprintf(`"%s"`, req.BlobSHA) +} diff --git a/internal/server/control/repositories/handlers.go b/internal/server/control/repositories/handlers.go index 588bdf1..62b3015 100644 --- a/internal/server/control/repositories/handlers.go +++ b/internal/server/control/repositories/handlers.go @@ -19,6 +19,8 @@ type RepositoryManager interface { Contents(ctx context.Context, repositoryID int64, ref, treePath string) (domain.RepositoryContents, error) PrepareArchive(ctx context.Context, repositoryID int64, ref, format string, includeLFS bool) (domain.ArchiveRequest, error) StreamArchive(ctx context.Context, req domain.ArchiveRequest, out io.Writer) error + PrepareBlob(ctx context.Context, repositoryID int64, ref, treePath string, includeLFS bool) (domain.BlobRequest, error) + StreamBlob(ctx context.Context, req domain.BlobRequest, out io.Writer) error } type handlers struct { @@ -39,6 +41,7 @@ func (h *handlers) RegisterRoutes(parent chi.Router) { r.Get("/{repositoryID}", response.Handler(h.logger, h.getRepository)) r.Get("/{repositoryID}/contents", response.Handler(h.logger, h.getContents)) r.Get("/{repositoryID}/archive", response.Handler(h.logger, h.getArchive)) + r.Get("/{repositoryID}/blob", response.Handler(h.logger, h.getBlob)) r.Put("/{repositoryID}/visibility", response.Handler(h.logger, h.setVisibility)) r.Delete("/{repositoryID}", response.Handler(h.logger, h.deleteRepository)) }) diff --git a/internal/server/control/repositories/handlers_test.go b/internal/server/control/repositories/handlers_test.go index 83af4aa..42966fe 100644 --- a/internal/server/control/repositories/handlers_test.go +++ b/internal/server/control/repositories/handlers_test.go @@ -2,11 +2,16 @@ package repositories import ( "archive/zip" + "bytes" "context" + "encoding/json" "io" "net/http" + "net/http/httptest" + "testing" "github.com/Axenos-dev/HeadlessGit/internal/domain" + reposervice "github.com/Axenos-dev/HeadlessGit/internal/services/repositories" "github.com/go-chi/chi/v5" "go.uber.org/zap" ) @@ -21,6 +26,9 @@ type fakeManager struct { prepareErr error streamBody string streamErr error + + blobReq domain.BlobRequest + blobErr error } func (f fakeManager) PrepareArchive(ctx context.Context, repositoryID int64, ref, format string, includeLFS bool) (domain.ArchiveRequest, error) { @@ -44,9 +52,242 @@ func (f fakeManager) StreamArchive(ctx context.Context, req domain.ArchiveReques return f.streamErr } +func (f fakeManager) PrepareBlob(ctx context.Context, repositoryID int64, ref, treePath string, includeLFS bool) (domain.BlobRequest, error) { + return f.blobReq, f.blobErr +} + +func (f fakeManager) StreamBlob(ctx context.Context, req domain.BlobRequest, out io.Writer) error { + if f.streamBody != "" { + if _, err := io.WriteString(out, f.streamBody); err != nil { + return err + } + } + return f.streamErr +} + // newTestRouter mounts the handlers the same way the control server does func newTestRouter(svc RepositoryManager) http.Handler { r := chi.NewRouter() NewHandlers(zap.NewNop(), svc).RegisterRoutes(r) return r } + +func testArchiveRequest() domain.ArchiveRequest { + return domain.ArchiveRequest{ + Repository: domain.Repository{ID: 7, RepositoryName: "myrepo"}, + CommitSHA: testSHA, + Format: domain.ArchiveFormatZip, + } +} + +func TestGetArchive(t *testing.T) { + router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), streamBody: "hello"}) + + rec := httptest.NewRecorder() + router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/repositories/7/archive?ref=main", nil)) + + if rec.Code != http.StatusOK { + t.Fatalf("status = %d, body %s", rec.Code, rec.Body.String()) + } + if got := rec.Header().Get("Content-Type"); got != "application/zip" { + t.Errorf("Content-Type = %q", got) + } + if got := rec.Header().Get("Content-Disposition"); got != `attachment; filename="myrepo-aaaabbbbcccc.zip"` { + t.Errorf("Content-Disposition = %q", got) + } + if got := rec.Header().Get("ETag"); got != `W/"`+testSHA+`-zip"` { + t.Errorf("ETag = %q", got) + } + if got := rec.Header().Get("X-HeadlessGit-Commit"); got != testSHA { + t.Errorf("X-HeadlessGit-Commit = %q", got) + } + + // the body must be a readable zip + zr, err := zip.NewReader(bytes.NewReader(rec.Body.Bytes()), int64(rec.Body.Len())) + if err != nil { + t.Fatal(err) + } + if len(zr.File) != 1 || zr.File[0].Name != "file.txt" { + t.Errorf("zip entries = %v", zr.File) + } +} + +func TestGetArchiveNotModified(t *testing.T) { + router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), streamBody: "hello"}) + + req := httptest.NewRequest(http.MethodGet, "/repositories/7/archive?ref=main", nil) + req.Header.Set("If-None-Match", `W/"`+testSHA+`-zip"`) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + if rec.Code != http.StatusNotModified { + t.Fatalf("status = %d", rec.Code) + } + if rec.Body.Len() != 0 { + t.Errorf("304 must have no body, got %d bytes", rec.Body.Len()) + } +} + +func TestGetArchiveErrors(t *testing.T) { + cases := []struct { + name string + target string + prepareErr error + streamErr error + wantStatus int + wantCode string + }{ + {"bad id", "/repositories/abc/archive", nil, nil, http.StatusBadRequest, "invalid_request"}, + {"bad lfs param", "/repositories/7/archive?lfs=maybe", nil, nil, http.StatusBadRequest, "invalid_request"}, + {"repo not found", "/repositories/7/archive", reposervice.ErrRepositoryNotFound, nil, http.StatusNotFound, "repository_not_found"}, + {"ref not found", "/repositories/7/archive?ref=nope", reposervice.ErrRefNotFound, nil, http.StatusNotFound, "ref_not_found"}, + {"invalid ref", "/repositories/7/archive?ref=--x", reposervice.ErrInvalidRef, nil, http.StatusBadRequest, "invalid_request"}, + {"bad format", "/repositories/7/archive?format=rar", reposervice.ErrUnsupportedFormat, nil, http.StatusBadRequest, "invalid_request"}, + {"lfs disabled", "/repositories/7/archive?lfs=true", reposervice.ErrLFSNotEnabled, nil, http.StatusBadRequest, "invalid_request"}, + {"stream fails before first byte", "/repositories/7/archive", nil, io.ErrUnexpectedEOF, http.StatusInternalServerError, "internal_error"}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), prepareErr: tc.prepareErr, streamErr: tc.streamErr}) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, tc.target, nil)) + + if rec.Code != tc.wantStatus { + t.Fatalf("status = %d, want %d: %s", rec.Code, tc.wantStatus, rec.Body.String()) + } + var body struct { + Error struct { + Code string `json:"code"` + } `json:"error"` + } + if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { + t.Fatal(err) + } + if body.Error.Code != tc.wantCode { + t.Errorf("code = %q, want %q", body.Error.Code, tc.wantCode) + } + if got := rec.Header().Get("Content-Disposition"); got != "" { + t.Errorf("error response leaked Content-Disposition %q", got) + } + }) + } +} + +func testBlobRequest(lfsOID string) domain.BlobRequest { + return domain.BlobRequest{ + Repository: domain.Repository{ID: 7, RepositoryName: "myrepo"}, + CommitSHA: testSHA, + BlobSHA: "1111222233334444555566667777888899990000", + Path: "src/main.go", + Size: 6, + LFSOID: lfsOID, + } +} + +func TestGetBlob(t *testing.T) { + router := newTestRouter(fakeManager{blobReq: testBlobRequest(""), streamBody: "hello\n"}) + + rec := httptest.NewRecorder() + router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/repositories/7/blob?ref=main&path=src/main.go", nil)) + + if rec.Code != http.StatusOK { + t.Fatalf("status = %d, body %s", rec.Code, rec.Body.String()) + } + if rec.Body.String() != "hello\n" { + t.Errorf("body = %q", rec.Body.String()) + } + if got := rec.Header().Get("ETag"); got != `"1111222233334444555566667777888899990000"` { + t.Errorf("ETag = %q", got) + } + if got := rec.Header().Get("Content-Length"); got != "6" { + t.Errorf("Content-Length = %q", got) + } + if got := rec.Header().Get("Content-Disposition"); got != `attachment; filename="main.go"` { + t.Errorf("Content-Disposition = %q", got) + } + if got := rec.Header().Get("X-HeadlessGit-Commit"); got != testSHA { + t.Errorf("X-HeadlessGit-Commit = %q", got) + } +} + +func TestGetBlobLFSVariantETag(t *testing.T) { + router := newTestRouter(fakeManager{blobReq: testBlobRequest("deadbeef"), streamBody: "hello\n"}) + + // the raw etag must not satisfy a smudged request + req := httptest.NewRequest(http.MethodGet, "/repositories/7/blob?ref=main&path=src/main.go&lfs=true", nil) + req.Header.Set("If-None-Match", `"1111222233334444555566667777888899990000"`) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + if rec.Code != http.StatusOK { + t.Fatalf("raw etag must not match lfs variant, status = %d", rec.Code) + } + if got := rec.Header().Get("ETag"); got != `"1111222233334444555566667777888899990000-lfs"` { + t.Errorf("ETag = %q", got) + } +} + +func TestGetBlobNotModified(t *testing.T) { + router := newTestRouter(fakeManager{blobReq: testBlobRequest(""), streamBody: "hello\n"}) + + req := httptest.NewRequest(http.MethodGet, "/repositories/7/blob?ref=main&path=src/main.go", nil) + req.Header.Set("If-None-Match", `"1111222233334444555566667777888899990000"`) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + + if rec.Code != http.StatusNotModified { + t.Fatalf("status = %d", rec.Code) + } + if rec.Body.Len() != 0 { + t.Errorf("304 must have no body, got %d bytes", rec.Body.Len()) + } +} + +func TestGetBlobErrors(t *testing.T) { + cases := []struct { + name string + target string + blobErr error + streamErr error + wantStatus int + wantCode string + }{ + {"bad id", "/repositories/abc/blob", nil, nil, http.StatusBadRequest, "invalid_request"}, + {"bad lfs param", "/repositories/7/blob?lfs=maybe", nil, nil, http.StatusBadRequest, "invalid_request"}, + {"repo not found", "/repositories/7/blob", reposervice.ErrRepositoryNotFound, nil, http.StatusNotFound, "repository_not_found"}, + {"ref not found", "/repositories/7/blob?ref=nope", reposervice.ErrRefNotFound, nil, http.StatusNotFound, "ref_not_found"}, + {"path not found", "/repositories/7/blob?path=nope", reposervice.ErrPathNotFound, nil, http.StatusNotFound, "path_not_found"}, + {"lfs object missing", "/repositories/7/blob?lfs=true", reposervice.ErrLFSObjectNotFound, nil, http.StatusNotFound, "lfs_object_not_found"}, + {"path is a directory", "/repositories/7/blob?path=src", reposervice.ErrNotAFile, nil, http.StatusBadRequest, "invalid_request"}, + {"invalid ref", "/repositories/7/blob?ref=--x", reposervice.ErrInvalidRef, nil, http.StatusBadRequest, "invalid_request"}, + {"lfs disabled", "/repositories/7/blob?lfs=true", reposervice.ErrLFSNotEnabled, nil, http.StatusBadRequest, "invalid_request"}, + {"stream fails before first byte", "/repositories/7/blob", nil, io.ErrUnexpectedEOF, http.StatusInternalServerError, "internal_error"}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + router := newTestRouter(fakeManager{blobReq: testBlobRequest(""), blobErr: tc.blobErr, streamErr: tc.streamErr}) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, tc.target, nil)) + + if rec.Code != tc.wantStatus { + t.Fatalf("status = %d, want %d: %s", rec.Code, tc.wantStatus, rec.Body.String()) + } + var body struct { + Error struct { + Code string `json:"code"` + } `json:"error"` + } + if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { + t.Fatal(err) + } + if body.Error.Code != tc.wantCode { + t.Errorf("code = %q, want %q", body.Error.Code, tc.wantCode) + } + if got := rec.Header().Get("Content-Disposition"); got != "" { + t.Errorf("error response leaked Content-Disposition %q", got) + } + }) + } +} diff --git a/internal/server/response/codes.go b/internal/server/response/codes.go index 552bea5..66f269b 100644 --- a/internal/server/response/codes.go +++ b/internal/server/response/codes.go @@ -12,4 +12,5 @@ const ( CodeTokenNotFound = "token_not_found" CodeRefNotFound = "ref_not_found" CodePathNotFound = "path_not_found" + CodeLFSObjectNotFound = "lfs_object_not_found" ) diff --git a/internal/services/repositories/archive_test.go b/internal/services/repositories/archive_test.go deleted file mode 100644 index 8adc36b..0000000 --- a/internal/services/repositories/archive_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package repositories - -import ( - "archive/tar" - "archive/zip" - "bytes" - "context" - "database/sql" - "errors" - "fmt" - "io" - "strings" - "testing" - - "github.com/Axenos-dev/HeadlessGit/internal/db/gen" - "github.com/Axenos-dev/HeadlessGit/internal/domain" - "github.com/Axenos-dev/HeadlessGit/internal/gitbackend" - "go.uber.org/zap" -) - -const testSHA = "aaaabbbbccccddddeeeeffff0000111122223333" - -type fakeRegistry struct { - Registry - repo gen.Repository - err error -} - -func (f fakeRegistry) GetRepository(ctx context.Context, repositoryID int64) (gen.Repository, error) { - return f.repo, f.err -} - -type fakeStorage struct { - RepositoryStorage - sha string - resolveErr error - tarBytes []byte -} - -func (f fakeStorage) ResolveCommit(ctx context.Context, storagePath, rev string) (string, error) { - if f.resolveErr != nil { - return "", f.resolveErr - } - return f.sha, nil -} - -func (f fakeStorage) ArchiveTar(ctx context.Context, storagePath, rev string, out io.Writer) (string, error) { - if _, err := out.Write(f.tarBytes); err != nil { - return "", err - } - return f.sha, nil -} - -type fakeLFS struct { - objects map[string]string // oid -> content -} - -func (f fakeLFS) GetObject(ctx context.Context, repo domain.Repository, oid string) (io.ReadCloser, int64, error) { - content, ok := f.objects[oid] - if !ok { - return nil, 0, errors.New("object not found") - } - return io.NopCloser(strings.NewReader(content)), int64(len(content)), nil -} - -func TestPrepareArchive(t *testing.T) { - row := gen.Repository{ID: 7, RepositoryName: "myrepo", StoragePath: "7/myrepo.git", Visibility: "private"} - - cases := []struct { - name string - registry Registry - storage RepositoryStorage - lfs LFSObjects - format string - includeLFS bool - wantErr error - }{ - {"unsupported format", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, nil, "rar", false, ErrUnsupportedFormat}, - {"lfs disabled", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, nil, "zip", true, ErrLFSNotEnabled}, - {"lfs enabled ok", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, fakeLFS{}, "zip", true, nil}, - {"repo not found", fakeRegistry{err: sql.ErrNoRows}, fakeStorage{sha: testSHA}, nil, "zip", false, ErrRepositoryNotFound}, - {"invalid ref", fakeRegistry{repo: row}, fakeStorage{resolveErr: gitbackend.ErrInvalidRev}, nil, "zip", false, ErrInvalidRef}, - {"ref not found", fakeRegistry{repo: row}, fakeStorage{resolveErr: gitbackend.ErrRevNotFound}, nil, "zip", false, ErrRefNotFound}, - {"ok", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, nil, "zip", false, nil}, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - svc := NewService(zap.NewNop(), tc.registry, tc.storage, tc.lfs) - req, err := svc.PrepareArchive(context.Background(), row.ID, "main", tc.format, tc.includeLFS) - if !errors.Is(err, tc.wantErr) { - t.Fatalf("PrepareArchive error = %v, want %v", err, tc.wantErr) - } - if tc.wantErr == nil { - if req.CommitSHA != testSHA || req.Repository.ID != row.ID || req.Format != domain.ArchiveFormatZip { - t.Errorf("PrepareArchive = %+v", req) - } - if want := "myrepo-aaaabbbbcccc.zip"; req.Filename() != want { - t.Errorf("Filename = %q, want %q", req.Filename(), want) - } - } - }) - } -} - -func TestStreamArchiveSmudgesLFS(t *testing.T) { - oid := strings.Repeat("ab", 32) - content := "REAL LFS CONTENT" - pointer := fmt.Sprintf("version https://git-lfs.github.com/spec/v1\noid sha256:%s\nsize %d\n", oid, len(content)) - - var tarBuf bytes.Buffer - tw := tar.NewWriter(&tarBuf) - for _, e := range []struct{ name, body string }{ - {"README.md", "hello\n"}, - {"big.bin", pointer}, - } { - if err := tw.WriteHeader(&tar.Header{Typeflag: tar.TypeReg, Name: e.name, Mode: 0o644, Size: int64(len(e.body))}); err != nil { - t.Fatal(err) - } - if _, err := tw.Write([]byte(e.body)); err != nil { - t.Fatal(err) - } - } - if err := tw.Close(); err != nil { - t.Fatal(err) - } - - svc := NewService( - zap.NewNop(), - fakeRegistry{}, - fakeStorage{sha: testSHA, tarBytes: tarBuf.Bytes()}, - fakeLFS{objects: map[string]string{oid: content}}, - ) - - req := domain.ArchiveRequest{ - Repository: domain.Repository{ID: 7, RepositoryName: "myrepo", StoragePath: "7/myrepo.git"}, - CommitSHA: testSHA, - Format: domain.ArchiveFormatZip, - IncludeLFS: true, - } - - var out bytes.Buffer - if err := svc.StreamArchive(context.Background(), req, &out); err != nil { - t.Fatal(err) - } - - zr, err := zip.NewReader(bytes.NewReader(out.Bytes()), int64(out.Len())) - if err != nil { - t.Fatal(err) - } - got := map[string]string{} - for _, f := range zr.File { - rc, err := f.Open() - if err != nil { - t.Fatal(err) - } - body, err := io.ReadAll(rc) - rc.Close() - if err != nil { - t.Fatal(err) - } - got[f.Name] = string(body) - } - - prefix := "myrepo-aaaabbbbcccc/" - if got[prefix+"big.bin"] != content { - t.Errorf("big.bin not smudged: %q", got[prefix+"big.bin"]) - } - if got[prefix+"README.md"] != "hello\n" { - t.Errorf("README.md = %q", got[prefix+"README.md"]) - } -} diff --git a/internal/services/repositories/errors.go b/internal/services/repositories/errors.go index cf129f2..7352ea8 100644 --- a/internal/services/repositories/errors.go +++ b/internal/services/repositories/errors.go @@ -14,4 +14,7 @@ var ( ErrUnsupportedFormat = errors.New("unsupported archive format") ErrLFSNotEnabled = errors.New("lfs is not enabled") + + ErrNotAFile = errors.New("path is not a file") + ErrLFSObjectNotFound = errors.New("lfs object not found") ) diff --git a/internal/services/repositories/service.go b/internal/services/repositories/service.go index 27ec4d5..2e56b59 100644 --- a/internal/services/repositories/service.go +++ b/internal/services/repositories/service.go @@ -1,6 +1,7 @@ package repositories import ( + "bytes" "context" "database/sql" "errors" @@ -32,6 +33,8 @@ type RepositoryStorage interface { ListTree(ctx context.Context, storagePath, rev, treePath string) (gitbackend.TreeListing, error) ResolveCommit(ctx context.Context, storagePath, rev string) (string, error) ArchiveTar(ctx context.Context, storagePath, rev string, out io.Writer) (string, error) + StatBlob(ctx context.Context, storagePath, rev, treePath string) (gitbackend.BlobInfo, error) + ReadBlob(ctx context.Context, storagePath, blobSHA string, out io.Writer) error } type LFSObjects interface { @@ -264,6 +267,79 @@ func (s *Service) StreamArchive(ctx context.Context, req domain.ArchiveRequest, return archive.Transform(pr, prefix, smudge, enc) } +func (s *Service) PrepareBlob(ctx context.Context, repositoryID int64, ref, treePath string, includeLFS bool) (domain.BlobRequest, error) { + if includeLFS && s.lfs == nil { + return domain.BlobRequest{}, ErrLFSNotEnabled + } + + repo, err := s.Get(ctx, repositoryID) + if err != nil { + return domain.BlobRequest{}, err + } + + info, err := s.storage.StatBlob(ctx, repo.StoragePath, ref, treePath) + switch { + case errors.Is(err, gitbackend.ErrInvalidRev): + return domain.BlobRequest{}, ErrInvalidRef + case errors.Is(err, gitbackend.ErrInvalidPath): + return domain.BlobRequest{}, ErrInvalidPath + case errors.Is(err, gitbackend.ErrRevNotFound): + return domain.BlobRequest{}, ErrRefNotFound + case errors.Is(err, gitbackend.ErrPathNotFound): + return domain.BlobRequest{}, ErrPathNotFound + case errors.Is(err, gitbackend.ErrNotABlob): + return domain.BlobRequest{}, ErrNotAFile + case err != nil: + return domain.BlobRequest{}, err + } + + req := domain.BlobRequest{ + Repository: repo, + CommitSHA: info.CommitSHA, + BlobSHA: info.BlobSHA, + Path: treePath, + Size: info.Size, + } + + // check pointer-sized blobs + if includeLFS && info.Size <= domain.LFSPointerMaxSize { + // read it + var buf bytes.Buffer + if err := s.storage.ReadBlob(ctx, repo.StoragePath, info.BlobSHA, &buf); err != nil { + return domain.BlobRequest{}, err + } + // then parse to see if its a pointer + if ptr, ok := domain.ParseLFSPointer(buf.Bytes()); ok { + // but the oid is repo content and untrusted + // so to be safe, we would pull it from dedicated lfs service with respect to repoID + rc, size, err := s.lfs.GetObject(ctx, repo, ptr.OID) + if err != nil { + return domain.BlobRequest{}, ErrLFSObjectNotFound + } + rc.Close() + + req.LFSOID = ptr.OID + req.Size = size + } + } + + return req, nil +} + +func (s *Service) StreamBlob(ctx context.Context, req domain.BlobRequest, out io.Writer) error { + if req.LFSOID != "" { + rc, _, err := s.lfs.GetObject(ctx, req.Repository, req.LFSOID) + if err != nil { + return err + } + defer rc.Close() + + _, err = io.Copy(out, rc) + return err + } + return s.storage.ReadBlob(ctx, req.Repository.StoragePath, req.BlobSHA, out) +} + func toDomain(r gen.Repository) domain.Repository { repo := domain.Repository{ ID: r.ID, diff --git a/internal/services/repositories/service_test.go b/internal/services/repositories/service_test.go new file mode 100644 index 0000000..de0a32b --- /dev/null +++ b/internal/services/repositories/service_test.go @@ -0,0 +1,312 @@ +package repositories + +import ( + "archive/tar" + "archive/zip" + "bytes" + "context" + "database/sql" + "errors" + "fmt" + "io" + "strings" + "testing" + + "github.com/Axenos-dev/HeadlessGit/internal/db/gen" + "github.com/Axenos-dev/HeadlessGit/internal/domain" + "github.com/Axenos-dev/HeadlessGit/internal/gitbackend" + "go.uber.org/zap" +) + +const testSHA = "aaaabbbbccccddddeeeeffff0000111122223333" + +type fakeRegistry struct { + Registry + repo gen.Repository + err error +} + +func (f fakeRegistry) GetRepository(ctx context.Context, repositoryID int64) (gen.Repository, error) { + return f.repo, f.err +} + +type fakeStorage struct { + RepositoryStorage + sha string + resolveErr error + tarBytes []byte + + blobInfo gitbackend.BlobInfo + blobStatErr error + blobContent string +} + +func (f fakeStorage) ResolveCommit(ctx context.Context, storagePath, rev string) (string, error) { + if f.resolveErr != nil { + return "", f.resolveErr + } + return f.sha, nil +} + +func (f fakeStorage) ArchiveTar(ctx context.Context, storagePath, rev string, out io.Writer) (string, error) { + if _, err := out.Write(f.tarBytes); err != nil { + return "", err + } + return f.sha, nil +} + +func (f fakeStorage) StatBlob(ctx context.Context, storagePath, rev, treePath string) (gitbackend.BlobInfo, error) { + if f.blobStatErr != nil { + return gitbackend.BlobInfo{}, f.blobStatErr + } + return f.blobInfo, nil +} + +func (f fakeStorage) ReadBlob(ctx context.Context, storagePath, blobSHA string, out io.Writer) error { + _, err := io.WriteString(out, f.blobContent) + return err +} + +type fakeLFS struct { + objects map[string]string // oid -> content +} + +func (f fakeLFS) GetObject(ctx context.Context, repo domain.Repository, oid string) (io.ReadCloser, int64, error) { + content, ok := f.objects[oid] + if !ok { + return nil, 0, errors.New("object not found") + } + return io.NopCloser(strings.NewReader(content)), int64(len(content)), nil +} + +func TestPrepareArchive(t *testing.T) { + row := gen.Repository{ID: 7, RepositoryName: "myrepo", StoragePath: "7/myrepo.git", Visibility: "private"} + + cases := []struct { + name string + registry Registry + storage RepositoryStorage + lfs LFSObjects + format string + includeLFS bool + wantErr error + }{ + {"unsupported format", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, nil, "rar", false, ErrUnsupportedFormat}, + {"lfs disabled", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, nil, "zip", true, ErrLFSNotEnabled}, + {"lfs enabled ok", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, fakeLFS{}, "zip", true, nil}, + {"repo not found", fakeRegistry{err: sql.ErrNoRows}, fakeStorage{sha: testSHA}, nil, "zip", false, ErrRepositoryNotFound}, + {"invalid ref", fakeRegistry{repo: row}, fakeStorage{resolveErr: gitbackend.ErrInvalidRev}, nil, "zip", false, ErrInvalidRef}, + {"ref not found", fakeRegistry{repo: row}, fakeStorage{resolveErr: gitbackend.ErrRevNotFound}, nil, "zip", false, ErrRefNotFound}, + {"ok", fakeRegistry{repo: row}, fakeStorage{sha: testSHA}, nil, "zip", false, nil}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + svc := NewService(zap.NewNop(), tc.registry, tc.storage, tc.lfs) + req, err := svc.PrepareArchive(context.Background(), row.ID, "main", tc.format, tc.includeLFS) + if !errors.Is(err, tc.wantErr) { + t.Fatalf("PrepareArchive error = %v, want %v", err, tc.wantErr) + } + if tc.wantErr == nil { + if req.CommitSHA != testSHA || req.Repository.ID != row.ID || req.Format != domain.ArchiveFormatZip { + t.Errorf("PrepareArchive = %+v", req) + } + if want := "myrepo-aaaabbbbcccc.zip"; req.Filename() != want { + t.Errorf("Filename = %q, want %q", req.Filename(), want) + } + } + }) + } +} + +func TestStreamArchiveSmudgesLFS(t *testing.T) { + oid := strings.Repeat("ab", 32) + content := "REAL LFS CONTENT" + pointer := fmt.Sprintf("version https://git-lfs.github.com/spec/v1\noid sha256:%s\nsize %d\n", oid, len(content)) + + var tarBuf bytes.Buffer + tw := tar.NewWriter(&tarBuf) + for _, e := range []struct{ name, body string }{ + {"README.md", "hello\n"}, + {"big.bin", pointer}, + } { + if err := tw.WriteHeader(&tar.Header{Typeflag: tar.TypeReg, Name: e.name, Mode: 0o644, Size: int64(len(e.body))}); err != nil { + t.Fatal(err) + } + if _, err := tw.Write([]byte(e.body)); err != nil { + t.Fatal(err) + } + } + if err := tw.Close(); err != nil { + t.Fatal(err) + } + + svc := NewService( + zap.NewNop(), + fakeRegistry{}, + fakeStorage{sha: testSHA, tarBytes: tarBuf.Bytes()}, + fakeLFS{objects: map[string]string{oid: content}}, + ) + + req := domain.ArchiveRequest{ + Repository: domain.Repository{ID: 7, RepositoryName: "myrepo", StoragePath: "7/myrepo.git"}, + CommitSHA: testSHA, + Format: domain.ArchiveFormatZip, + IncludeLFS: true, + } + + var out bytes.Buffer + if err := svc.StreamArchive(context.Background(), req, &out); err != nil { + t.Fatal(err) + } + + zr, err := zip.NewReader(bytes.NewReader(out.Bytes()), int64(out.Len())) + if err != nil { + t.Fatal(err) + } + got := map[string]string{} + for _, f := range zr.File { + rc, err := f.Open() + if err != nil { + t.Fatal(err) + } + body, err := io.ReadAll(rc) + rc.Close() + if err != nil { + t.Fatal(err) + } + got[f.Name] = string(body) + } + + prefix := "myrepo-aaaabbbbcccc/" + if got[prefix+"big.bin"] != content { + t.Errorf("big.bin not smudged: %q", got[prefix+"big.bin"]) + } + if got[prefix+"README.md"] != "hello\n" { + t.Errorf("README.md = %q", got[prefix+"README.md"]) + } +} + +const blobSHA = "1111222233334444555566667777888899990000" + +func blobStorage(content string) fakeStorage { + return fakeStorage{ + blobInfo: gitbackend.BlobInfo{CommitSHA: testSHA, BlobSHA: blobSHA, Size: int64(len(content))}, + blobContent: content, + } +} + +func TestPrepareBlob(t *testing.T) { + row := gen.Repository{ID: 7, RepositoryName: "myrepo", StoragePath: "7/myrepo.git", Visibility: "private"} + oid := strings.Repeat("cd", 32) + content := "REAL LFS CONTENT" + pointer := fmt.Sprintf("version https://git-lfs.github.com/spec/v1\noid sha256:%s\nsize %d\n", oid, len(content)) + + t.Run("raw file", func(t *testing.T) { + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage("hello\n"), nil) + req, err := svc.PrepareBlob(context.Background(), row.ID, "main", "README.md", false) + if err != nil { + t.Fatal(err) + } + if req.BlobSHA != blobSHA || req.CommitSHA != testSHA || req.Size != 6 || req.LFSOID != "" { + t.Errorf("PrepareBlob = %+v", req) + } + }) + + t.Run("pointer smudged", func(t *testing.T) { + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage(pointer), fakeLFS{objects: map[string]string{oid: content}}) + req, err := svc.PrepareBlob(context.Background(), row.ID, "main", "big.bin", true) + if err != nil { + t.Fatal(err) + } + if req.LFSOID != oid { + t.Errorf("LFSOID = %q", req.LFSOID) + } + if req.Size != int64(len(content)) { + t.Errorf("Size = %d, want object size %d", req.Size, len(content)) + } + }) + + t.Run("pointer without lfs flag stays raw", func(t *testing.T) { + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage(pointer), fakeLFS{objects: map[string]string{oid: content}}) + req, err := svc.PrepareBlob(context.Background(), row.ID, "main", "big.bin", false) + if err != nil { + t.Fatal(err) + } + if req.LFSOID != "" || req.Size != int64(len(pointer)) { + t.Errorf("PrepareBlob = %+v", req) + } + }) + + t.Run("large blob is never sniffed", func(t *testing.T) { + st := blobStorage(pointer) + st.blobInfo.Size = 5000 // over the pointer cap, content must not be read + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, st, fakeLFS{}) + req, err := svc.PrepareBlob(context.Background(), row.ID, "main", "big.bin", true) + if err != nil { + t.Fatal(err) + } + if req.LFSOID != "" || req.Size != 5000 { + t.Errorf("PrepareBlob = %+v", req) + } + }) + + t.Run("missing lfs object fails loudly", func(t *testing.T) { + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage(pointer), fakeLFS{}) + if _, err := svc.PrepareBlob(context.Background(), row.ID, "main", "big.bin", true); !errors.Is(err, ErrLFSObjectNotFound) { + t.Errorf("want ErrLFSObjectNotFound, got %v", err) + } + }) + + t.Run("errors", func(t *testing.T) { + cases := []struct { + name string + storage RepositoryStorage + lfs LFSObjects + includeLFS bool + wantErr error + }{ + {"lfs disabled", blobStorage(""), nil, true, ErrLFSNotEnabled}, + {"not a file", fakeStorage{blobStatErr: gitbackend.ErrNotABlob}, nil, false, ErrNotAFile}, + {"path not found", fakeStorage{blobStatErr: gitbackend.ErrPathNotFound}, nil, false, ErrPathNotFound}, + {"ref not found", fakeStorage{blobStatErr: gitbackend.ErrRevNotFound}, nil, false, ErrRefNotFound}, + {"invalid ref", fakeStorage{blobStatErr: gitbackend.ErrInvalidRev}, nil, false, ErrInvalidRef}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, tc.storage, tc.lfs) + if _, err := svc.PrepareBlob(context.Background(), row.ID, "main", "x", tc.includeLFS); !errors.Is(err, tc.wantErr) { + t.Errorf("PrepareBlob error = %v, want %v", err, tc.wantErr) + } + }) + } + }) +} + +func TestStreamBlob(t *testing.T) { + oid := strings.Repeat("cd", 32) + content := "REAL LFS CONTENT" + repo := domain.Repository{ID: 7, RepositoryName: "myrepo", StoragePath: "7/myrepo.git"} + + t.Run("raw", func(t *testing.T) { + svc := NewService(zap.NewNop(), fakeRegistry{}, blobStorage("hello\n"), nil) + var out bytes.Buffer + if err := svc.StreamBlob(context.Background(), domain.BlobRequest{Repository: repo, BlobSHA: blobSHA}, &out); err != nil { + t.Fatal(err) + } + if out.String() != "hello\n" { + t.Errorf("content = %q", out.String()) + } + }) + + t.Run("smudged", func(t *testing.T) { + svc := NewService(zap.NewNop(), fakeRegistry{}, blobStorage(""), fakeLFS{objects: map[string]string{oid: content}}) + var out bytes.Buffer + if err := svc.StreamBlob(context.Background(), domain.BlobRequest{Repository: repo, BlobSHA: blobSHA, LFSOID: oid}, &out); err != nil { + t.Fatal(err) + } + if out.String() != content { + t.Errorf("content = %q", out.String()) + } + }) +} From 39ceb8421db292c43fa3c6e28322fc156bf77a4c Mon Sep 17 00:00:00 2001 From: Axenos-dev Date: Sun, 5 Jul 2026 20:02:18 -0700 Subject: [PATCH 4/7] Upload blob to ODB endpoint --- internal/gitbackend/backend.go | 1 + internal/gitbackend/local.go | 32 ++++++++ internal/gitbackend/local_test.go | 41 ++++++++++ internal/server/control/repositories/blob.go | 21 +++++ .../server/control/repositories/handlers.go | 2 + .../control/repositories/handlers_test.go | 78 +++++++++++++++++++ internal/server/control/repositories/types.go | 5 ++ internal/services/repositories/service.go | 10 +++ 8 files changed, 190 insertions(+) diff --git a/internal/gitbackend/backend.go b/internal/gitbackend/backend.go index 844c549..fe45dba 100644 --- a/internal/gitbackend/backend.go +++ b/internal/gitbackend/backend.go @@ -17,4 +17,5 @@ type Backend interface { ArchiveTar(ctx context.Context, storagePath, rev string, out io.Writer) (string, error) StatBlob(ctx context.Context, storagePath, rev, treePath string) (BlobInfo, error) ReadBlob(ctx context.Context, storagePath, blobSHA string, out io.Writer) error + WriteBlob(ctx context.Context, storagePath string, r io.Reader) (string, int64, error) } diff --git a/internal/gitbackend/local.go b/internal/gitbackend/local.go index b094bbd..ff05cf6 100644 --- a/internal/gitbackend/local.go +++ b/internal/gitbackend/local.go @@ -359,6 +359,26 @@ func (l *Local) ResolveCommit(ctx context.Context, storagePath, rev string) (str return commitSHA, nil } +func (l *Local) WriteBlob(ctx context.Context, storagePath string, r io.Reader) (string, int64, error) { + dir, err := l.resolve(storagePath) + if err != nil { + return "", 0, err + } + + counter := &countingReader{r: r} + cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "hash-object", "-w", "--stdin") + cmd.Stdin = counter + + var out, stderr bytes.Buffer + cmd.Stdout = &out + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return "", 0, fmt.Errorf("hash-object: %w: %s", err, strings.TrimSpace(stderr.String())) + } + + return strings.TrimSpace(out.String()), counter.n, nil +} + // revParse resolves a rev expression to an object id, failing when the object does not exist func (l *Local) revParse(ctx context.Context, dir, spec string) (string, error) { cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "rev-parse", "--verify", "--end-of-options", spec) @@ -497,3 +517,15 @@ func isHexSHA(s string) bool { } return true } + +// just to keep track how much bytes were streamed +type countingReader struct { + r io.Reader + n int64 +} + +func (c *countingReader) Read(p []byte) (int, error) { + n, err := c.r.Read(p) + c.n += int64(n) + return n, err +} diff --git a/internal/gitbackend/local_test.go b/internal/gitbackend/local_test.go index 55012ac..4e2ed1c 100644 --- a/internal/gitbackend/local_test.go +++ b/internal/gitbackend/local_test.go @@ -405,6 +405,47 @@ func TestBlob(t *testing.T) { t.Errorf("content = %q", buf.String()) } + t.Run("write blob", func(t *testing.T) { + // git blob shas are deterministic: "hello\n" is famously 0xce0136... + sha, size, err := l.WriteBlob(ctx, "1/test.git", strings.NewReader("hello\n")) + if err != nil { + t.Fatal(err) + } + if sha != "ce013625030ba8dba906f756967f9e9ca394464a" { + t.Errorf("sha = %q", sha) + } + if size != 6 { + t.Errorf("size = %d", size) + } + + // the object must be readable back before any commit references it + var buf bytes.Buffer + if err := l.ReadBlob(ctx, "1/test.git", sha, &buf); err != nil { + t.Fatal(err) + } + if buf.String() != "hello\n" { + t.Errorf("content = %q", buf.String()) + } + + // uploading the same content again dedupes to the same sha + again, _, err := l.WriteBlob(ctx, "1/test.git", strings.NewReader("hello\n")) + if err != nil { + t.Fatal(err) + } + if again != sha { + t.Errorf("re-upload sha = %q, want %q", again, sha) + } + + // empty content is the canonical empty blob + empty, size, err := l.WriteBlob(ctx, "1/test.git", strings.NewReader("")) + if err != nil { + t.Fatal(err) + } + if empty != "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391" || size != 0 { + t.Errorf("empty blob = %q size %d", empty, size) + } + }) + t.Run("errors", func(t *testing.T) { cases := []struct { name, rev, path string diff --git a/internal/server/control/repositories/blob.go b/internal/server/control/repositories/blob.go index 248434c..fc57edd 100644 --- a/internal/server/control/repositories/blob.go +++ b/internal/server/control/repositories/blob.go @@ -14,6 +14,27 @@ import ( "go.uber.org/zap" ) +func (h *handlers) uploadBlob(w http.ResponseWriter, r *http.Request) error { + id, err := strconv.ParseInt(chi.URLParam(r, "repositoryID"), 10, 64) + if err != nil { + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid repository id") + } + + sha, byteCount, err := h.service.WriteBlob(r.Context(), id, r.Body) + switch { + case errors.Is(err, reposervice.ErrRepositoryNotFound): + return response.NewError(http.StatusNotFound, response.CodeRepositoryNotFound, "repository not found") + case err != nil: + h.logger.Error("failed to write blob", zap.Error(err)) + return response.NewError(http.StatusInternalServerError, response.CodeInternalError, "failed to write blob") + } + + return response.Data(w, http.StatusCreated, UploadBlobResponse{ + SHA: sha, + Size: byteCount, + }) +} + func (h *handlers) getBlob(w http.ResponseWriter, r *http.Request) error { id, err := strconv.ParseInt(chi.URLParam(r, "repositoryID"), 10, 64) if err != nil { diff --git a/internal/server/control/repositories/handlers.go b/internal/server/control/repositories/handlers.go index 62b3015..fcfc066 100644 --- a/internal/server/control/repositories/handlers.go +++ b/internal/server/control/repositories/handlers.go @@ -21,6 +21,7 @@ type RepositoryManager interface { StreamArchive(ctx context.Context, req domain.ArchiveRequest, out io.Writer) error PrepareBlob(ctx context.Context, repositoryID int64, ref, treePath string, includeLFS bool) (domain.BlobRequest, error) StreamBlob(ctx context.Context, req domain.BlobRequest, out io.Writer) error + WriteBlob(ctx context.Context, repositoryID int64, in io.Reader) (string, int64, error) } type handlers struct { @@ -38,6 +39,7 @@ func NewHandlers(logger *zap.Logger, service RepositoryManager) *handlers { func (h *handlers) RegisterRoutes(parent chi.Router) { parent.Route("/repositories", func(r chi.Router) { r.Post("/", response.Handler(h.logger, h.createRepository)) + r.Post("/{repositoryID}/blobs", response.Handler(h.logger, h.uploadBlob)) r.Get("/{repositoryID}", response.Handler(h.logger, h.getRepository)) r.Get("/{repositoryID}/contents", response.Handler(h.logger, h.getContents)) r.Get("/{repositoryID}/archive", response.Handler(h.logger, h.getArchive)) diff --git a/internal/server/control/repositories/handlers_test.go b/internal/server/control/repositories/handlers_test.go index 42966fe..d4ebb5b 100644 --- a/internal/server/control/repositories/handlers_test.go +++ b/internal/server/control/repositories/handlers_test.go @@ -8,6 +8,7 @@ import ( "io" "net/http" "net/http/httptest" + "strings" "testing" "github.com/Axenos-dev/HeadlessGit/internal/domain" @@ -29,6 +30,9 @@ type fakeManager struct { blobReq domain.BlobRequest blobErr error + + writeSHA string + writeErr error } func (f fakeManager) PrepareArchive(ctx context.Context, repositoryID int64, ref, format string, includeLFS bool) (domain.ArchiveRequest, error) { @@ -65,6 +69,17 @@ func (f fakeManager) StreamBlob(ctx context.Context, req domain.BlobRequest, out return f.streamErr } +func (f fakeManager) WriteBlob(ctx context.Context, repositoryID int64, in io.Reader) (string, int64, error) { + n, err := io.Copy(io.Discard, in) // consume the stream like the real thing + if err != nil { + return "", 0, err + } + if f.writeErr != nil { + return "", 0, f.writeErr + } + return f.writeSHA, n, nil +} + // newTestRouter mounts the handlers the same way the control server does func newTestRouter(svc RepositoryManager) http.Handler { r := chi.NewRouter() @@ -244,6 +259,69 @@ func TestGetBlobNotModified(t *testing.T) { } } +func TestUploadBlob(t *testing.T) { + router := newTestRouter(fakeManager{writeSHA: "ce013625030ba8dba906f756967f9e9ca394464a"}) + + rec := httptest.NewRecorder() + router.ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "/repositories/7/blobs", strings.NewReader("hello\n"))) + + if rec.Code != http.StatusCreated { + t.Fatalf("status = %d, body %s", rec.Code, rec.Body.String()) + } + var body struct { + Data struct { + SHA string `json:"sha"` + Size int64 `json:"size"` + } `json:"data"` + } + if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { + t.Fatal(err) + } + if body.Data.SHA != "ce013625030ba8dba906f756967f9e9ca394464a" { + t.Errorf("sha = %q", body.Data.SHA) + } + if body.Data.Size != 6 { + t.Errorf("size = %d", body.Data.Size) + } +} + +func TestUploadBlobErrors(t *testing.T) { + cases := []struct { + name string + target string + writeErr error + wantStatus int + wantCode string + }{ + {"bad id", "/repositories/abc/blobs", nil, http.StatusBadRequest, "invalid_request"}, + {"repo not found", "/repositories/7/blobs", reposervice.ErrRepositoryNotFound, http.StatusNotFound, "repository_not_found"}, + {"write fails", "/repositories/7/blobs", io.ErrUnexpectedEOF, http.StatusInternalServerError, "internal_error"}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + router := newTestRouter(fakeManager{writeErr: tc.writeErr}) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, httptest.NewRequest(http.MethodPost, tc.target, strings.NewReader("x"))) + + if rec.Code != tc.wantStatus { + t.Fatalf("status = %d, want %d: %s", rec.Code, tc.wantStatus, rec.Body.String()) + } + var body struct { + Error struct { + Code string `json:"code"` + } `json:"error"` + } + if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { + t.Fatal(err) + } + if body.Error.Code != tc.wantCode { + t.Errorf("code = %q, want %q", body.Error.Code, tc.wantCode) + } + }) + } +} + func TestGetBlobErrors(t *testing.T) { cases := []struct { name string diff --git a/internal/server/control/repositories/types.go b/internal/server/control/repositories/types.go index 0f5e346..8e95aa4 100644 --- a/internal/server/control/repositories/types.go +++ b/internal/server/control/repositories/types.go @@ -110,3 +110,8 @@ func (r UpdateVisibilityRequest) Validate() error { } return nil } + +type UploadBlobResponse struct { + SHA string `json:"sha"` + Size int64 `json:"size"` +} diff --git a/internal/services/repositories/service.go b/internal/services/repositories/service.go index 2e56b59..4719854 100644 --- a/internal/services/repositories/service.go +++ b/internal/services/repositories/service.go @@ -35,6 +35,7 @@ type RepositoryStorage interface { ArchiveTar(ctx context.Context, storagePath, rev string, out io.Writer) (string, error) StatBlob(ctx context.Context, storagePath, rev, treePath string) (gitbackend.BlobInfo, error) ReadBlob(ctx context.Context, storagePath, blobSHA string, out io.Writer) error + WriteBlob(ctx context.Context, storagePath string, r io.Reader) (string, int64, error) } type LFSObjects interface { @@ -340,6 +341,15 @@ func (s *Service) StreamBlob(ctx context.Context, req domain.BlobRequest, out io return s.storage.ReadBlob(ctx, req.Repository.StoragePath, req.BlobSHA, out) } +func (s *Service) WriteBlob(ctx context.Context, repositoryID int64, in io.Reader) (string, int64, error) { + repo, err := s.Get(ctx, repositoryID) + if err != nil { + return "", 0, err + } + + return s.storage.WriteBlob(ctx, repo.StoragePath, in) +} + func toDomain(r gen.Repository) domain.Repository { repo := domain.Repository{ ID: r.ID, From af8f6927768751e689ea52371caf9b190b2df620 Mon Sep 17 00:00:00 2001 From: Axenos-dev Date: Mon, 6 Jul 2026 11:30:09 -0700 Subject: [PATCH 5/7] Commit API on control plane --- AGENTS.md | 17 +- cmd/app/main.go | 11 +- internal/domain/commit.go | 28 ++ internal/gitbackend/backend.go | 1 + internal/gitbackend/errors.go | 8 + internal/gitbackend/local.go | 402 ++++++++++++++++-- internal/gitbackend/local_test.go | 182 ++++++++ internal/gitbackend/types.go | 27 ++ .../server/control/repositories/commits.go | 75 ++++ .../server/control/repositories/handlers.go | 2 + .../control/repositories/handlers_test.go | 152 ++++++- internal/server/control/repositories/types.go | 69 +++ internal/server/git/githttp/e2e_test.go | 2 +- internal/server/git/githttp/lfs_e2e_test.go | 2 +- internal/server/response/codes.go | 4 + internal/services/lfs/service.go | 22 + internal/services/repositories/errors.go | 7 + internal/services/repositories/service.go | 149 ++++++- .../services/repositories/service_test.go | 231 +++++++++- 19 files changed, 1316 insertions(+), 75 deletions(-) create mode 100644 internal/domain/commit.go create mode 100644 internal/server/control/repositories/commits.go diff --git a/AGENTS.md b/AGENTS.md index 424173c..167ad87 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,8 +11,10 @@ It provides: - Git over SSH and HTTP (clone / fetch / push). - Git LFS (object transfer over HTTP; disk or S3 storage). - A control API to manage repositories, users, SSH keys, tokens, permissions, and webhooks. -- Read-only repo APIs on the control plane: contents listing (`ls-tree`) and - streamed zip/tar.gz archives (`git archive`, optional in-flight LFS smudging). +- Repo APIs on the control plane: contents listing, blob read/upload, streamed + zip/tar.gz archives (optional LFS smudging), and commit creation on bare repos + (blobs + commits, CAS ref updates, `.gitattributes`-driven LFS cleaning) — so + products never need local clones. - A `read` / `write` / `admin` permission model enforced before every Git operation. - Push webhooks, signed and delivered off the push path. @@ -55,7 +57,7 @@ Package map: | `internal/services/*` | Business logic per area (repositories, users, auth, permissions, lfs); each has a service + a registry over `db`. | | `internal/storage` | LFS object storage behind an interface (`disk`, `s3`). | | `internal/archive` | Pure mechanism: streaming tar re-encode to zip/tar.gz with an injected LFS smudge callback. | -| `internal/gitbackend` | Git subprocesses behind a small interface: pack protocol plus read ops (ls-tree, rev resolution, tar archive). | +| `internal/gitbackend` | Git subprocesses behind a small interface: pack protocol, read ops (ls-tree, blobs, archive), commit creation. | | `internal/server` | Composition root: wires control + git servers, runs and shuts down listeners. | | `internal/server/control` | Control API (REST); sub-handlers in `repositories/`, `users/`, `permissions/`. | | `internal/server/git/gitssh` | Git-over-SSH transport (custom in-process SSH server). | @@ -154,10 +156,11 @@ storage clients. Do not roll your own SSH or Git protocol implementation. ## Webhooks -- Emitted only **after** a successful push, off the push path: receive-pack runs, - `gitbackend` diffs the repo's refs before/after, and the transport hands the - changes to the webhooks service. Delivery is an in-process bounded queue with - worker goroutines and retries — no external job system. +- Emitted only **after** a ref actually moved, off the push path: receive-pack + runs and `gitbackend` diffs the repo's refs before/after (transports dispatch), + or an api commit lands its CAS ref update (repositories service dispatches). + Both produce identical push events. Delivery is an in-process bounded queue + with worker goroutines and retries — no external job system. - One delivery per changed ref. Payload is self-describing: `event`, `ref`, `before`/`after`, `created`/`deleted`, a `repository` object (`id`, `name`, `full_name`), a `pusher` object (`id`, `username`), and `timestamp`. Creates/ diff --git a/cmd/app/main.go b/cmd/app/main.go index abfb719..752185f 100644 --- a/cmd/app/main.go +++ b/cmd/app/main.go @@ -79,11 +79,17 @@ func main() { repoLFS = lfsService } + webhooksService := webhooks.NewService( + root.With(zap.String("service", "webhooks")), + webhooks.NewRegistry(db), + ) + repoService := repositories.NewService( root.With(zap.String("service", "repositories")), repositories.NewRegistry(db), gitBackend, repoLFS, + webhooksService, ) authService := auth.NewService( @@ -100,11 +106,6 @@ func main() { permsService := permissions.NewService(permissions.NewRegistry(db)) usersService := users.NewService(users.NewRegistry(db)) - webhooksService := webhooks.NewService( - root.With(zap.String("service", "webhooks")), - webhooks.NewRegistry(db), - ) - ctx, stop := signal.NotifyContext( context.Background(), syscall.SIGINT, diff --git a/internal/domain/commit.go b/internal/domain/commit.go new file mode 100644 index 0000000..868358e --- /dev/null +++ b/internal/domain/commit.go @@ -0,0 +1,28 @@ +package domain + +type CommitIdentity struct { + Name string + Email string +} + +type CommitFileOp struct { + Delete bool + Path string + BlobSHA string + Executable bool +} + +type CommitRequest struct { + Branch string + Message string + Author CommitIdentity + ExpectedHeadSHA string // pins the commit to an exact branch state + PusherID int64 // optionally attributes the push event to an account + Operations []CommitFileOp +} + +type CommitResult struct { + Branch string + CommitSHA string + Before string // the branch head the commit was built on; all-zero for a new branch +} diff --git a/internal/gitbackend/backend.go b/internal/gitbackend/backend.go index fe45dba..6850b98 100644 --- a/internal/gitbackend/backend.go +++ b/internal/gitbackend/backend.go @@ -18,4 +18,5 @@ type Backend interface { StatBlob(ctx context.Context, storagePath, rev, treePath string) (BlobInfo, error) ReadBlob(ctx context.Context, storagePath, blobSHA string, out io.Writer) error WriteBlob(ctx context.Context, storagePath string, r io.Reader) (string, int64, error) + ApplyCommit(ctx context.Context, storagePath string, spec CommitSpec, ops []CommitOp, clean CleanFunc) (RefChange, error) } diff --git a/internal/gitbackend/errors.go b/internal/gitbackend/errors.go index ec83f9f..43351e8 100644 --- a/internal/gitbackend/errors.go +++ b/internal/gitbackend/errors.go @@ -8,4 +8,12 @@ var ( ErrRevNotFound = errors.New("revision not found") ErrPathNotFound = errors.New("path not found in tree") ErrNotABlob = errors.New("path is not a blob") + + // commit creation + ErrInvalidBranch = errors.New("invalid branch name") + ErrInvalidOps = errors.New("invalid commit operations") + ErrUnknownBlob = errors.New("blob not found in repository") + ErrHeadMismatch = errors.New("branch head mismatch") + ErrNothingToCommit = errors.New("nothing to commit") + ErrLFSRequired = errors.New("path is lfs-tracked but no clean filter is available") ) diff --git a/internal/gitbackend/local.go b/internal/gitbackend/local.go index ff05cf6..0be0e22 100644 --- a/internal/gitbackend/local.go +++ b/internal/gitbackend/local.go @@ -1,7 +1,6 @@ package gitbackend import ( - "bufio" "bytes" "context" "fmt" @@ -176,28 +175,21 @@ func (l *Local) listRefs(ctx context.Context, storagePath string) (map[string]st return nil, err } - ctx, cancel := context.WithTimeout(ctx, l.timeout) - defer cancel() - - cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "for-each-ref", "--format=%(objectname) %(refname)") - var out, stderr bytes.Buffer - cmd.Stdout = &out - cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { - return nil, fmt.Errorf("for-each-ref: %w: %s", err, strings.TrimSpace(stderr.String())) + out, err := l.runGit(ctx, dir, nil, nil, "for-each-ref", "--format=%(objectname) %(refname)") + if err != nil { + return nil, err } refs := make(map[string]string) - sc := bufio.NewScanner(&out) - for sc.Scan() { + for line := range strings.SplitSeq(out, "\n") { // cut the string by " ", to separate sha from ref - sha, ref, ok := strings.Cut(sc.Text(), " ") + sha, ref, ok := strings.Cut(line, " ") if !ok { continue } refs[ref] = sha } - return refs, sc.Err() + return refs, nil } func (l *Local) ListTree(ctx context.Context, storagePath, rev, treePath string) (TreeListing, error) { @@ -216,24 +208,18 @@ func (l *Local) ListTree(ctx context.Context, storagePath, rev, treePath string) return TreeListing{}, err } - ctx, cancel := context.WithTimeout(ctx, l.timeout) - defer cancel() - treeish := commitSHA if treePath != "" { treeish += ":" + treePath } - cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "ls-tree", "--long", "-z", "--end-of-options", treeish) - var out, stderr bytes.Buffer - cmd.Stdout = &out - cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { + out, err := l.runGit(ctx, dir, nil, nil, "ls-tree", "--long", "-z", "--end-of-options", treeish) + if err != nil { // the rev already resolved, so this is a missing path or a non-directory return TreeListing{}, fmt.Errorf("%w: %q", ErrPathNotFound, treePath) } - entries, truncated, err := parseLsTree(out.Bytes(), treePath) + entries, truncated, err := parseLsTree([]byte(out), treePath) if err != nil { return TreeListing{}, err } @@ -284,27 +270,20 @@ func (l *Local) StatBlob(ctx context.Context, storagePath, rev, treePath string) return BlobInfo{}, err } - ctx, cancel := context.WithTimeout(ctx, l.timeout) - defer cancel() - blobSHA, err := l.revParse(ctx, dir, commitSHA+":"+treePath) if err != nil { return BlobInfo{}, fmt.Errorf("%w: %q", ErrPathNotFound, treePath) } - cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "cat-file", "--batch-check") - cmd.Stdin = strings.NewReader(blobSHA + "\n") - var out, stderr bytes.Buffer - cmd.Stdout = &out - cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { - return BlobInfo{}, fmt.Errorf("cat-file --batch-check: %w: %s", err, strings.TrimSpace(stderr.String())) + out, err := l.runGit(ctx, dir, nil, strings.NewReader(blobSHA+"\n"), "cat-file", "--batch-check") + if err != nil { + return BlobInfo{}, err } // output shape: " " - fields := strings.Fields(out.String()) + fields := strings.Fields(out) if len(fields) != 3 { - return BlobInfo{}, fmt.Errorf("malformed batch-check output: %q", out.String()) + return BlobInfo{}, fmt.Errorf("malformed batch-check output: %q", out) } if fields[1] != "blob" { return BlobInfo{}, fmt.Errorf("%w: %q is a %s", ErrNotABlob, treePath, fields[1]) @@ -348,9 +327,6 @@ func (l *Local) ResolveCommit(ctx context.Context, storagePath, rev string) (str return "", err } - ctx, cancel := context.WithTimeout(ctx, l.timeout) - defer cancel() - // ^{commit} forces the object to exist and peel to a commit commitSHA, err := l.revParse(ctx, dir, rev+"^{commit}") if err != nil { @@ -379,18 +355,360 @@ func (l *Local) WriteBlob(ctx context.Context, storagePath string, r io.Reader) return strings.TrimSpace(out.String()), counter.n, nil } -// revParse resolves a rev expression to an object id, failing when the object does not exist -func (l *Local) revParse(ctx context.Context, dir, spec string) (string, error) { - cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "rev-parse", "--verify", "--end-of-options", spec) +// creates a commit on a branch from already-uploaded blobs +func (l *Local) ApplyCommit(ctx context.Context, storagePath string, spec CommitSpec, ops []CommitOp, clean CleanFunc) (RefChange, error) { + dir, err := l.resolve(storagePath) + if err != nil { + return RefChange{}, err + } + + spec, err = l.validateCommitSpec(ctx, dir, spec) + if err != nil { + return RefChange{}, err + } + ops, err = validateCommitOps(ops) + if err != nil { + return RefChange{}, err + } + + // resolve the current branch head + ref := "refs/heads/" + spec.Branch + oldSHA, err := l.revParse(ctx, dir, ref) + unborn := err != nil + switch { + case unborn && spec.ExpectedOld != zeroSHA: + return RefChange{}, fmt.Errorf("%w: branch %s", ErrRevNotFound, spec.Branch) + case !unborn && spec.ExpectedOld == zeroSHA: + return RefChange{}, fmt.Errorf("%w: branch %s already exists", ErrHeadMismatch, spec.Branch) + case !unborn && spec.ExpectedOld != "" && spec.ExpectedOld != oldSHA: + return RefChange{}, fmt.Errorf("%w: expected %s, head is %s", ErrHeadMismatch, spec.ExpectedOld, oldSHA) + } + if unborn { + oldSHA = zeroSHA + } + + // one batch-check verifies every referenced blob (and captures sizes for + // the clean filter) plus the existence of every delete target + sizes, err := l.verifyCommitInputs(ctx, dir, oldSHA, unborn, ops) + if err != nil { + return RefChange{}, err + } + + // private index file: commits never touch the repo's real index (bare + // repos have none) and concurrent commits cannot see each other + idx, err := os.CreateTemp(dir, "headlessgit-index-*") + if err != nil { + return RefChange{}, fmt.Errorf("create temp index: %w", err) + } + idx.Close() + defer os.Remove(idx.Name()) + env := []string{"GIT_INDEX_FILE=" + idx.Name()} + + if unborn { + if _, err := l.runGit(ctx, dir, env, nil, "read-tree", "--empty"); err != nil { + return RefChange{}, err + } + } else { + if _, err := l.runGit(ctx, dir, env, nil, "read-tree", oldSHA); err != nil { + return RefChange{}, err + } + } + + // .gitattributes changes land first, so lfs tracking added in this very + // commit already applies to the files committed alongside it + attrOps, fileOps := splitAttrOps(ops) + if err := l.updateIndex(ctx, dir, env, attrOps); err != nil { + return RefChange{}, err + } + + fileOps, err = l.cleanLFSTracked(ctx, dir, env, fileOps, sizes, clean) + if err != nil { + return RefChange{}, err + } + if err := l.updateIndex(ctx, dir, env, fileOps); err != nil { + return RefChange{}, err + } + + treeSHA, err := l.runGit(ctx, dir, env, nil, "write-tree") + if err != nil { + return RefChange{}, fmt.Errorf("%w: %s", ErrInvalidOps, err) + } + if !unborn { + oldTree, err := l.revParse(ctx, dir, oldSHA+"^{tree}") + if err != nil { + return RefChange{}, err + } + if treeSHA == oldTree { + return RefChange{}, ErrNothingToCommit + } + } + + commitEnv := []string{ + "GIT_AUTHOR_NAME=" + spec.Author.Name, + "GIT_AUTHOR_EMAIL=" + spec.Author.Email, + "GIT_COMMITTER_NAME=" + spec.Committer.Name, + "GIT_COMMITTER_EMAIL=" + spec.Committer.Email, + } + args := []string{"commit-tree", treeSHA} + if !unborn { + args = append(args, "-p", oldSHA) + } + args = append(args, "-m", spec.Message) + newSHA, err := l.runGit(ctx, dir, commitEnv, nil, args...) + if err != nil { + return RefChange{}, err + } + + // update-ref only moves the branch if it still points at oldSHA + if _, err := l.runGit(ctx, dir, nil, nil, "update-ref", ref, newSHA, oldSHA); err != nil { + return RefChange{}, fmt.Errorf("%w: %s", ErrHeadMismatch, err) + } + + return RefChange{Ref: ref, OldSHA: oldSHA, NewSHA: newSHA}, nil +} + +// validateCommitSpec checks the branch name and identities +func (l *Local) validateCommitSpec(ctx context.Context, dir string, spec CommitSpec) (CommitSpec, error) { + if spec.Branch == "" || strings.HasPrefix(spec.Branch, "-") { + return spec, fmt.Errorf("%w: %q", ErrInvalidBranch, spec.Branch) + } + for _, r := range spec.Branch { + if r < 0x20 || r == 0x7f { + return spec, fmt.Errorf("%w: control character", ErrInvalidBranch) + } + } + // git itself is the authority on ref name rules + if _, err := l.runGit(ctx, dir, nil, nil, "check-ref-format", "--branch", spec.Branch); err != nil { + return spec, fmt.Errorf("%w: %q", ErrInvalidBranch, spec.Branch) + } + + if spec.ExpectedOld != "" && !isHexSHA(spec.ExpectedOld) { + return spec, fmt.Errorf("%w: expected old %q", ErrInvalidRev, spec.ExpectedOld) + } + if spec.Author.Name == "" || spec.Author.Email == "" { + return spec, fmt.Errorf("%w: author name and email are required", ErrInvalidOps) + } + if spec.Committer.Name == "" { + spec.Committer = spec.Author + } + if spec.Message == "" { + return spec, fmt.Errorf("%w: message is required", ErrInvalidOps) + } + return spec, nil +} + +// normalizes paths and enforces the op rules +func validateCommitOps(ops []CommitOp) ([]CommitOp, error) { + if len(ops) == 0 { + return nil, fmt.Errorf("%w: no operations", ErrInvalidOps) + } + if len(ops) > maxCommitOps { + return nil, fmt.Errorf("%w: more than %d operations", ErrInvalidOps, maxCommitOps) + } + + out := make([]CommitOp, len(ops)) + seen := make(map[string]bool, len(ops)) + for i, op := range ops { + p, err := normalizeTreePath(op.Path) + if err != nil || p == "" { + return nil, fmt.Errorf("%w: path %q", ErrInvalidOps, op.Path) + } + // the batch-check and check-attr line protocols cannot carry these + for _, r := range p { + if r < 0x20 || r == 0x7f { + return nil, fmt.Errorf("%w: control character in path", ErrInvalidOps) + } + } + if seen[p] { + return nil, fmt.Errorf("%w: duplicate path %q", ErrInvalidOps, p) + } + seen[p] = true + + op.Path = p + if !op.Delete { + if !isHexSHA(op.BlobSHA) { + return nil, fmt.Errorf("%w: blob sha %q", ErrInvalidOps, op.BlobSHA) + } + switch op.Mode { + case "": + op.Mode = "100644" + case "100644", "100755": + default: + return nil, fmt.Errorf("%w: mode %q", ErrInvalidOps, op.Mode) + } + } + out[i] = op + } + return out, nil +} + +// runs one cat-file --batch-check over every put blob sha (returning their sizes) +// and every delete target +// so unknown blobs and missing delete paths fail +func (l *Local) verifyCommitInputs(ctx context.Context, dir, oldSHA string, unborn bool, ops []CommitOp) (map[string]int64, error) { + var in strings.Builder + type query struct { + op CommitOp + isPut bool + } + var queries []query + for _, op := range ops { + if op.Delete { + if unborn { + return nil, fmt.Errorf("%w: %q", ErrPathNotFound, op.Path) + } + in.WriteString(oldSHA + ":" + op.Path + "\n") + } else { + in.WriteString(op.BlobSHA + "\n") + } + queries = append(queries, query{op: op, isPut: !op.Delete}) + } + + out, err := l.runGit(ctx, dir, nil, strings.NewReader(in.String()), "cat-file", "--batch-check") + if err != nil { + return nil, err + } + + lines := strings.Split(out, "\n") + if len(lines) != len(queries) { + return nil, fmt.Errorf("unexpected batch-check output: %d lines for %d queries", len(lines), len(queries)) + } + + sizes := make(map[string]int64) + for i, line := range lines { + q := queries[i] + fields := strings.Fields(line) + switch { + case len(fields) >= 2 && fields[len(fields)-1] == "missing": + if q.isPut { + return nil, fmt.Errorf("%w: %s", ErrUnknownBlob, q.op.BlobSHA) + } + return nil, fmt.Errorf("%w: %q", ErrPathNotFound, q.op.Path) + case len(fields) == 3 && fields[1] == "blob": + size, err := strconv.ParseInt(fields[2], 10, 64) + if err != nil { + return nil, fmt.Errorf("malformed batch-check size %q: %w", fields[2], err) + } + if q.isPut { + sizes[q.op.BlobSHA] = size + } + case len(fields) == 3: + // a delete target resolving to a tree or a put sha naming a non-blob + if q.isPut { + return nil, fmt.Errorf("%w: %s is a %s", ErrUnknownBlob, q.op.BlobSHA, fields[1]) + } + return nil, fmt.Errorf("%w: %q is a %s", ErrNotABlob, q.op.Path, fields[1]) + default: + return nil, fmt.Errorf("malformed batch-check line: %q", line) + } + } + return sizes, nil +} + +// separates .gitattributes changes from regular file changes +func splitAttrOps(ops []CommitOp) (attr, files []CommitOp) { + for _, op := range ops { + if op.Path == ".gitattributes" || strings.HasSuffix(op.Path, "/.gitattributes") { + attr = append(attr, op) + } else { + files = append(files, op) + } + } + return attr, files +} + +// asks git which put paths are lfs-tracked, +// and swaps their blobs for the pointer blobs produced by the clean filter +func (l *Local) cleanLFSTracked(ctx context.Context, dir string, env []string, ops []CommitOp, sizes map[string]int64, clean CleanFunc) ([]CommitOp, error) { + var paths []string + byPath := make(map[string]int) + for i, op := range ops { + if !op.Delete { + paths = append(paths, op.Path) + byPath[op.Path] = i + } + } + if len(paths) == 0 { + return ops, nil + } + + args := append([]string{"check-attr", "-z", "--cached", "filter", "--"}, paths...) + out, err := l.runGit(ctx, dir, env, nil, args...) + if err != nil { + return nil, err + } + + // -z output is NUL-separated (path, attr, value) triples + fields := strings.Split(out, "\x00") + for i := 0; i+2 < len(fields); i += 3 { + path, value := fields[i], fields[i+2] + if value != "lfs" { + continue + } + idx, ok := byPath[path] + if !ok { + continue + } + if clean == nil { + return nil, fmt.Errorf("%w: %q", ErrLFSRequired, path) + } + + pointerSHA, err := clean(path, ops[idx].BlobSHA, sizes[ops[idx].BlobSHA]) + if err != nil { + return nil, fmt.Errorf("lfs clean %q: %w", path, err) + } + if !isHexSHA(pointerSHA) { + return nil, fmt.Errorf("lfs clean %q returned invalid sha %q", path, pointerSHA) + } + ops[idx].BlobSHA = pointerSHA + } + return ops, nil +} + +// applies puts and deletes in one subprocess +func (l *Local) updateIndex(ctx context.Context, dir string, env []string, ops []CommitOp) error { + if len(ops) == 0 { + return nil + } + var in strings.Builder + for _, op := range ops { + if op.Delete { + in.WriteString("0 " + zeroSHA + "\t" + op.Path + "\x00") + } else { + in.WriteString(op.Mode + " " + op.BlobSHA + "\t" + op.Path + "\x00") + } + } + if _, err := l.runGit(ctx, dir, env, strings.NewReader(in.String()), "update-index", "-z", "--index-info"); err != nil { + return fmt.Errorf("%w: %s", ErrInvalidOps, err) + } + return nil +} + +// runGit executes one short-lived git command with the repo as context, +// applying the standard timeout, and returns its trimmed stdout +func (l *Local) runGit(ctx context.Context, dir string, env []string, stdin io.Reader, args ...string) (string, error) { + ctx, cancel := context.WithTimeout(ctx, l.timeout) + defer cancel() + + cmd := exec.CommandContext(ctx, l.gitPath, append([]string{"-C", dir}, args...)...) + if len(env) > 0 { + cmd.Env = append(os.Environ(), env...) + } + cmd.Stdin = stdin var out, stderr bytes.Buffer cmd.Stdout = &out cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - return "", fmt.Errorf("rev-parse: %w: %s", err, strings.TrimSpace(stderr.String())) + return "", fmt.Errorf("git %s: %w: %s", args[0], err, strings.TrimSpace(stderr.String())) } return strings.TrimSpace(out.String()), nil } +// revParse resolves a rev expression to an object id, failing when the object does not exist +func (l *Local) revParse(ctx context.Context, dir, spec string) (string, error) { + return l.runGit(ctx, dir, nil, nil, "rev-parse", "--verify", "--end-of-options", spec) +} + func parseLsTree(out []byte, treePath string) ([]TreeEntry, bool, error) { var entries []TreeEntry // each record has a shape like " \t" diff --git a/internal/gitbackend/local_test.go b/internal/gitbackend/local_test.go index 4e2ed1c..2c88959 100644 --- a/internal/gitbackend/local_test.go +++ b/internal/gitbackend/local_test.go @@ -28,6 +28,17 @@ func gitRun(t *testing.T, dir string, args ...string) { } } +// like gitRun but returns the trimmed stdout +func gitOut(t *testing.T, dir string, args ...string) string { + t.Helper() + cmd := exec.Command("git", append([]string{"-C", dir}, args...)...) + out, err := cmd.Output() + if err != nil { + t.Fatalf("git %v: %v", args, err) + } + return strings.TrimSpace(string(out)) +} + func TestResolveContainment(t *testing.T) { root := "/srv/repos" l := &Local{root: root} @@ -474,6 +485,177 @@ func TestBlob(t *testing.T) { }) } +func TestApplyCommit(t *testing.T) { + if _, err := exec.LookPath("git"); err != nil { + t.Skip("git not on PATH") + } + + root := t.TempDir() + l, err := NewLocal(root) + if err != nil { + t.Fatal(err) + } + ctx := context.Background() + const repo = "1/test.git" + + if err := l.InitBare(ctx, repo); err != nil { + t.Fatal(err) + } + + author := Identity{Name: "api-user", Email: "api@test"} + spec := func(expectedOld, msg string) CommitSpec { + return CommitSpec{Branch: "main", ExpectedOld: expectedOld, Author: author, Message: msg} + } + blob := func(content string) string { + t.Helper() + sha, _, err := l.WriteBlob(ctx, repo, strings.NewReader(content)) + if err != nil { + t.Fatal(err) + } + return sha + } + + hello := blob("hello\n") + script := blob("#!/bin/sh\n") + + // creating a branch requires explicitly expecting non-existence + if _, err := l.ApplyCommit(ctx, repo, spec("", "init"), []CommitOp{{Path: "README.md", BlobSHA: hello}}, nil); !errors.Is(err, ErrRevNotFound) { + t.Fatalf("missing branch without zero expected-old: want ErrRevNotFound, got %v", err) + } + + first, err := l.ApplyCommit(ctx, repo, spec(zeroSHA, "init"), []CommitOp{ + {Path: "README.md", BlobSHA: hello}, + {Path: "src/run.sh", BlobSHA: script, Mode: "100755"}, + }, nil) + if err != nil { + t.Fatal(err) + } + if first.OldSHA != zeroSHA || !isHexSHA(first.NewSHA) || first.Ref != "refs/heads/main" { + t.Fatalf("first change = %+v", first) + } + + // a real git client must see exactly what we committed + wt := filepath.Join(t.TempDir(), "wt") + gitRun(t, ".", "clone", "-b", "main", filepath.Join(root, repo), wt) + + readme, err := os.ReadFile(filepath.Join(wt, "README.md")) + if err != nil || string(readme) != "hello\n" { + t.Errorf("README.md = %q, %v", readme, err) + } + info, err := os.Stat(filepath.Join(wt, "src", "run.sh")) + if err != nil { + t.Fatal(err) + } + if info.Mode()&0o100 == 0 { + t.Errorf("run.sh not executable: %v", info.Mode()) + } + + logOut := gitOut(t, wt, "log", "-1", "--format=%H|%an|%ae|%s") + if logOut != first.NewSHA+"|api-user|api@test|init" { + t.Errorf("log = %q", logOut) + } + + // second commit: CAS on the known head, update one file, delete another + v2 := blob("hello v2\n") + second, err := l.ApplyCommit(ctx, repo, spec(first.NewSHA, "update"), []CommitOp{ + {Path: "README.md", BlobSHA: v2}, + {Path: "src/run.sh", Delete: true}, + }, nil) + if err != nil { + t.Fatal(err) + } + if second.OldSHA != first.NewSHA { + t.Errorf("second change = %+v", second) + } + + gitRun(t, wt, "pull") + if readme, _ := os.ReadFile(filepath.Join(wt, "README.md")); string(readme) != "hello v2\n" { + t.Errorf("README.md after pull = %q", readme) + } + if _, err := os.Stat(filepath.Join(wt, "src", "run.sh")); !os.IsNotExist(err) { + t.Errorf("run.sh should be deleted, stat err = %v", err) + } + + t.Run("errors", func(t *testing.T) { + cases := []struct { + name string + spec CommitSpec + ops []CommitOp + want error + }{ + {"stale cas", spec(first.NewSHA, "x"), []CommitOp{{Path: "a", BlobSHA: hello}}, ErrHeadMismatch}, + {"create existing branch", spec(zeroSHA, "x"), []CommitOp{{Path: "a", BlobSHA: hello}}, ErrHeadMismatch}, + {"unknown blob", spec("", "x"), []CommitOp{{Path: "a", BlobSHA: strings.Repeat("d", 40)}}, ErrUnknownBlob}, + {"nothing to commit", spec("", "x"), []CommitOp{{Path: "README.md", BlobSHA: v2}}, ErrNothingToCommit}, + {"delete missing path", spec("", "x"), []CommitOp{{Path: "nope.txt", Delete: true}}, ErrPathNotFound}, + {"bad branch", CommitSpec{Branch: "a..b", ExpectedOld: "", Author: author, Message: "x"}, []CommitOp{{Path: "a", BlobSHA: hello}}, ErrInvalidBranch}, + {"hostile branch", CommitSpec{Branch: "--help", Author: author, Message: "x"}, []CommitOp{{Path: "a", BlobSHA: hello}}, ErrInvalidBranch}, + {"no ops", spec("", "x"), nil, ErrInvalidOps}, + {"duplicate path", spec("", "x"), []CommitOp{{Path: "a", BlobSHA: hello}, {Path: "a", Delete: true}}, ErrInvalidOps}, + {"bad mode", spec("", "x"), []CommitOp{{Path: "a", BlobSHA: hello, Mode: "120000"}}, ErrInvalidOps}, + {"missing author", CommitSpec{Branch: "main", Author: Identity{}, Message: "x"}, []CommitOp{{Path: "a", BlobSHA: hello}}, ErrInvalidOps}, + {"missing message", CommitSpec{Branch: "main", Author: author}, []CommitOp{{Path: "a", BlobSHA: hello}}, ErrInvalidOps}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if _, err := l.ApplyCommit(ctx, repo, tc.spec, tc.ops, nil); !errors.Is(err, tc.want) { + t.Errorf("ApplyCommit = %v, want %v", err, tc.want) + } + }) + } + }) + + t.Run("lfs clean", func(t *testing.T) { + attrs := blob("*.bin filter=lfs diff=lfs merge=lfs -text\n") + payload := blob("REAL BINARY CONTENT") + pointerText := "version https://git-lfs.github.com/spec/v1\noid sha256:" + strings.Repeat("ab", 32) + "\nsize 19\n" + pointer := blob(pointerText) + + // tracked path without a clean filter fails loudly + if _, err := l.ApplyCommit(ctx, repo, spec("", "track"), []CommitOp{ + {Path: ".gitattributes", BlobSHA: attrs}, + {Path: "big.bin", BlobSHA: payload}, + }, nil); !errors.Is(err, ErrLFSRequired) { + t.Fatalf("want ErrLFSRequired, got %v", err) + } + + // tracking added in the SAME commit must clean the file next to it + var gotPath, gotSHA string + var gotSize int64 + clean := func(path, blobSHA string, size int64) (string, error) { + gotPath, gotSHA, gotSize = path, blobSHA, size + return pointer, nil + } + change, err := l.ApplyCommit(ctx, repo, spec("", "track + add"), []CommitOp{ + {Path: ".gitattributes", BlobSHA: attrs}, + {Path: "big.bin", BlobSHA: payload}, + {Path: "notes.txt", BlobSHA: hello}, // untracked, must NOT be cleaned + }, clean) + if err != nil { + t.Fatal(err) + } + if gotPath != "big.bin" || gotSHA != payload || gotSize != 19 { + t.Errorf("clean called with (%q, %q, %d)", gotPath, gotSHA, gotSize) + } + + // the committed tree holds the pointer, not the payload + committed, err := l.StatBlob(ctx, repo, change.NewSHA, "big.bin") + if err != nil { + t.Fatal(err) + } + if committed.BlobSHA != pointer { + t.Errorf("big.bin blob = %s, want pointer %s", committed.BlobSHA, pointer) + } + notes, err := l.StatBlob(ctx, repo, change.NewSHA, "notes.txt") + if err != nil { + t.Fatal(err) + } + if notes.BlobSHA != hello { + t.Errorf("notes.txt was cleaned but is not lfs-tracked") + } + }) +} + func TestDiffRefs(t *testing.T) { cases := []struct { name string diff --git a/internal/gitbackend/types.go b/internal/gitbackend/types.go index 5bb6e8b..cfb1622 100644 --- a/internal/gitbackend/types.go +++ b/internal/gitbackend/types.go @@ -8,6 +8,9 @@ const zeroSHA = "0000000000000000000000000000000000000000" // hard cap on entries returned per directory level const maxTreeEntries = 10_000 +// hard cap on operations per commit +const maxCommitOps = 1000 + type RefChange struct { Ref string OldSHA string @@ -33,3 +36,27 @@ type BlobInfo struct { BlobSHA string Size int64 } + +type CommitOp struct { + Delete bool + Path string + BlobSHA string // puts only; must exist as a blob in this repo's odb + Mode string // puts only: "100644" (default) or "100755" +} + +type Identity struct { + Name string + Email string +} + +type CommitSpec struct { + Branch string + // ExpectedOld pins the commit to an exact branch state + ExpectedOld string + Author Identity + Committer Identity // defaults to Author when empty + Message string +} + +// write-side mirror of archive.SmudgeFunc +type CleanFunc func(path, blobSHA string, size int64) (string, error) diff --git a/internal/server/control/repositories/commits.go b/internal/server/control/repositories/commits.go new file mode 100644 index 0000000..908309c --- /dev/null +++ b/internal/server/control/repositories/commits.go @@ -0,0 +1,75 @@ +package repositories + +import ( + "encoding/json" + "errors" + "net/http" + "strconv" + + "github.com/Axenos-dev/HeadlessGit/internal/domain" + "github.com/Axenos-dev/HeadlessGit/internal/server/response" + reposervice "github.com/Axenos-dev/HeadlessGit/internal/services/repositories" + "github.com/go-chi/chi/v5" + "go.uber.org/zap" +) + +func (h *handlers) createCommit(w http.ResponseWriter, r *http.Request) error { + id, err := strconv.ParseInt(chi.URLParam(r, "repositoryID"), 10, 64) + if err != nil { + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid repository id") + } + + var req CreateCommitRequest + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid request body") + } + if err := req.Validate(); err != nil { + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, err.Error()) + } + + ops := make([]domain.CommitFileOp, len(req.Operations)) + for i, op := range req.Operations { + ops[i] = domain.CommitFileOp{ + Delete: op.Op == "delete", + Path: op.Path, + BlobSHA: op.BlobSHA, + Executable: op.Executable, + } + } + + result, err := h.service.Commit(r.Context(), id, domain.CommitRequest{ + Branch: req.Branch, + Message: req.Message, + Author: domain.CommitIdentity{Name: req.Author.Name, Email: req.Author.Email}, + ExpectedHeadSHA: req.ExpectedHeadSHA, + PusherID: req.PusherID, + Operations: ops, + }) + switch { + case errors.Is(err, reposervice.ErrRepositoryNotFound): + return response.NewError(http.StatusNotFound, response.CodeRepositoryNotFound, "repository not found") + case errors.Is(err, reposervice.ErrRefNotFound): + return response.NewError(http.StatusNotFound, response.CodeRefNotFound, "branch not found; pass the all-zero expectedHeadSha to create it") + case errors.Is(err, reposervice.ErrPathNotFound): + return response.NewError(http.StatusNotFound, response.CodePathNotFound, "delete target not found") + case errors.Is(err, reposervice.ErrHeadMismatch): + return response.NewError(http.StatusConflict, response.CodeHeadMismatch, "branch head does not match expectedHeadSha") + case errors.Is(err, reposervice.ErrUnknownBlob): + return response.NewError(http.StatusUnprocessableEntity, response.CodeUnknownBlob, "referenced blob not found, upload it first") + case errors.Is(err, reposervice.ErrNothingToCommit): + return response.NewError(http.StatusUnprocessableEntity, response.CodeNothingToCommit, "operations produce no change") + case errors.Is(err, reposervice.ErrNotAFile): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "delete target is not a file") + case errors.Is(err, reposervice.ErrInvalidBranch): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "invalid branch name") + case errors.Is(err, reposervice.ErrInvalidCommitOps): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, err.Error()) + case errors.Is(err, reposervice.ErrLFSNotEnabled): + return response.NewError(http.StatusBadRequest, response.CodeInvalidRequest, "path is lfs-tracked but lfs is not enabled") + case err != nil: + h.logger.Error("failed to create commit", zap.Error(err)) + return response.NewError(http.StatusInternalServerError, response.CodeInternalError, "failed to create commit") + } + + return response.Data(w, http.StatusCreated, newCommit(result)) +} diff --git a/internal/server/control/repositories/handlers.go b/internal/server/control/repositories/handlers.go index fcfc066..4158525 100644 --- a/internal/server/control/repositories/handlers.go +++ b/internal/server/control/repositories/handlers.go @@ -22,6 +22,7 @@ type RepositoryManager interface { PrepareBlob(ctx context.Context, repositoryID int64, ref, treePath string, includeLFS bool) (domain.BlobRequest, error) StreamBlob(ctx context.Context, req domain.BlobRequest, out io.Writer) error WriteBlob(ctx context.Context, repositoryID int64, in io.Reader) (string, int64, error) + Commit(ctx context.Context, repositoryID int64, req domain.CommitRequest) (domain.CommitResult, error) } type handlers struct { @@ -40,6 +41,7 @@ func (h *handlers) RegisterRoutes(parent chi.Router) { parent.Route("/repositories", func(r chi.Router) { r.Post("/", response.Handler(h.logger, h.createRepository)) r.Post("/{repositoryID}/blobs", response.Handler(h.logger, h.uploadBlob)) + r.Post("/{repositoryID}/commits", response.Handler(h.logger, h.createCommit)) r.Get("/{repositoryID}", response.Handler(h.logger, h.getRepository)) r.Get("/{repositoryID}/contents", response.Handler(h.logger, h.getContents)) r.Get("/{repositoryID}/archive", response.Handler(h.logger, h.getArchive)) diff --git a/internal/server/control/repositories/handlers_test.go b/internal/server/control/repositories/handlers_test.go index d4ebb5b..3099943 100644 --- a/internal/server/control/repositories/handlers_test.go +++ b/internal/server/control/repositories/handlers_test.go @@ -33,6 +33,17 @@ type fakeManager struct { writeSHA string writeErr error + + commitResult domain.CommitResult + commitErr error + commitReq domain.CommitRequest + commitCalled bool +} + +func (f *fakeManager) Commit(ctx context.Context, repositoryID int64, req domain.CommitRequest) (domain.CommitResult, error) { + f.commitCalled = true + f.commitReq = req + return f.commitResult, f.commitErr } func (f fakeManager) PrepareArchive(ctx context.Context, repositoryID int64, ref, format string, includeLFS bool) (domain.ArchiveRequest, error) { @@ -96,7 +107,7 @@ func testArchiveRequest() domain.ArchiveRequest { } func TestGetArchive(t *testing.T) { - router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), streamBody: "hello"}) + router := newTestRouter(&fakeManager{prepareReq: testArchiveRequest(), streamBody: "hello"}) rec := httptest.NewRecorder() router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/repositories/7/archive?ref=main", nil)) @@ -128,7 +139,7 @@ func TestGetArchive(t *testing.T) { } func TestGetArchiveNotModified(t *testing.T) { - router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), streamBody: "hello"}) + router := newTestRouter(&fakeManager{prepareReq: testArchiveRequest(), streamBody: "hello"}) req := httptest.NewRequest(http.MethodGet, "/repositories/7/archive?ref=main", nil) req.Header.Set("If-None-Match", `W/"`+testSHA+`-zip"`) @@ -164,7 +175,7 @@ func TestGetArchiveErrors(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - router := newTestRouter(fakeManager{prepareReq: testArchiveRequest(), prepareErr: tc.prepareErr, streamErr: tc.streamErr}) + router := newTestRouter(&fakeManager{prepareReq: testArchiveRequest(), prepareErr: tc.prepareErr, streamErr: tc.streamErr}) rec := httptest.NewRecorder() router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, tc.target, nil)) @@ -201,7 +212,7 @@ func testBlobRequest(lfsOID string) domain.BlobRequest { } func TestGetBlob(t *testing.T) { - router := newTestRouter(fakeManager{blobReq: testBlobRequest(""), streamBody: "hello\n"}) + router := newTestRouter(&fakeManager{blobReq: testBlobRequest(""), streamBody: "hello\n"}) rec := httptest.NewRecorder() router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/repositories/7/blob?ref=main&path=src/main.go", nil)) @@ -227,7 +238,7 @@ func TestGetBlob(t *testing.T) { } func TestGetBlobLFSVariantETag(t *testing.T) { - router := newTestRouter(fakeManager{blobReq: testBlobRequest("deadbeef"), streamBody: "hello\n"}) + router := newTestRouter(&fakeManager{blobReq: testBlobRequest("deadbeef"), streamBody: "hello\n"}) // the raw etag must not satisfy a smudged request req := httptest.NewRequest(http.MethodGet, "/repositories/7/blob?ref=main&path=src/main.go&lfs=true", nil) @@ -244,7 +255,7 @@ func TestGetBlobLFSVariantETag(t *testing.T) { } func TestGetBlobNotModified(t *testing.T) { - router := newTestRouter(fakeManager{blobReq: testBlobRequest(""), streamBody: "hello\n"}) + router := newTestRouter(&fakeManager{blobReq: testBlobRequest(""), streamBody: "hello\n"}) req := httptest.NewRequest(http.MethodGet, "/repositories/7/blob?ref=main&path=src/main.go", nil) req.Header.Set("If-None-Match", `"1111222233334444555566667777888899990000"`) @@ -260,7 +271,7 @@ func TestGetBlobNotModified(t *testing.T) { } func TestUploadBlob(t *testing.T) { - router := newTestRouter(fakeManager{writeSHA: "ce013625030ba8dba906f756967f9e9ca394464a"}) + router := newTestRouter(&fakeManager{writeSHA: "ce013625030ba8dba906f756967f9e9ca394464a"}) rec := httptest.NewRecorder() router.ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "/repositories/7/blobs", strings.NewReader("hello\n"))) @@ -300,7 +311,7 @@ func TestUploadBlobErrors(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - router := newTestRouter(fakeManager{writeErr: tc.writeErr}) + router := newTestRouter(&fakeManager{writeErr: tc.writeErr}) rec := httptest.NewRecorder() router.ServeHTTP(rec, httptest.NewRequest(http.MethodPost, tc.target, strings.NewReader("x"))) @@ -345,7 +356,7 @@ func TestGetBlobErrors(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - router := newTestRouter(fakeManager{blobReq: testBlobRequest(""), blobErr: tc.blobErr, streamErr: tc.streamErr}) + router := newTestRouter(&fakeManager{blobReq: testBlobRequest(""), blobErr: tc.blobErr, streamErr: tc.streamErr}) rec := httptest.NewRecorder() router.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, tc.target, nil)) @@ -369,3 +380,126 @@ func TestGetBlobErrors(t *testing.T) { }) } } + +func validCommitBody() string { + return `{ + "branch": "main", + "message": "update", + "author": {"name": "api-user", "email": "api@test"}, + "expectedHeadSha": "` + strings.Repeat("a", 40) + `", + "pusherId": 42, + "operations": [ + {"op": "put", "path": "run.sh", "blobSha": "` + strings.Repeat("b", 40) + `", "executable": true}, + {"op": "delete", "path": "old.txt"} + ] + }` +} + +func TestCreateCommit(t *testing.T) { + result := domain.CommitResult{Branch: "main", CommitSHA: testSHA, Before: strings.Repeat("a", 40)} + fake := &fakeManager{commitResult: result} + + rec := httptest.NewRecorder() + newTestRouter(fake).ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "/repositories/7/commits", strings.NewReader(validCommitBody()))) + + if rec.Code != http.StatusCreated { + t.Fatalf("status = %d, body %s", rec.Code, rec.Body.String()) + } + + var body struct { + Data Commit `json:"data"` + } + if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { + t.Fatal(err) + } + if body.Data.CommitSHA != testSHA || body.Data.Before != result.Before || body.Data.Branch != "main" { + t.Errorf("body = %+v", body.Data) + } + + // the service must receive the fully mapped domain request + req := fake.commitReq + if req.Branch != "main" || req.Message != "update" || req.PusherID != 42 || + req.Author.Name != "api-user" || req.ExpectedHeadSHA != strings.Repeat("a", 40) { + t.Errorf("service request = %+v", req) + } + if len(req.Operations) != 2 || + req.Operations[0].Delete || !req.Operations[0].Executable || req.Operations[0].BlobSHA != strings.Repeat("b", 40) || + !req.Operations[1].Delete || req.Operations[1].Path != "old.txt" { + t.Errorf("service operations = %+v", req.Operations) + } +} + +func TestCreateCommitValidation(t *testing.T) { + cases := []struct { + name string + body string + }{ + {"not json", "nope"}, + {"missing branch", `{"message":"x","author":{"name":"a","email":"e"},"operations":[{"op":"delete","path":"a"}]}`}, + {"missing message", `{"branch":"main","author":{"name":"a","email":"e"},"operations":[{"op":"delete","path":"a"}]}`}, + {"missing author", `{"branch":"main","message":"x","operations":[{"op":"delete","path":"a"}]}`}, + {"no operations", `{"branch":"main","message":"x","author":{"name":"a","email":"e"},"operations":[]}`}, + {"bad op kind", `{"branch":"main","message":"x","author":{"name":"a","email":"e"},"operations":[{"op":"move","path":"a"}]}`}, + {"put without blobSha", `{"branch":"main","message":"x","author":{"name":"a","email":"e"},"operations":[{"op":"put","path":"a"}]}`}, + {"delete with blobSha", `{"branch":"main","message":"x","author":{"name":"a","email":"e"},"operations":[{"op":"delete","path":"a","blobSha":"abc"}]}`}, + {"missing path", `{"branch":"main","message":"x","author":{"name":"a","email":"e"},"operations":[{"op":"delete"}]}`}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + fake := &fakeManager{} + rec := httptest.NewRecorder() + newTestRouter(fake).ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "/repositories/7/commits", strings.NewReader(tc.body))) + + if rec.Code != http.StatusBadRequest { + t.Fatalf("status = %d, body %s", rec.Code, rec.Body.String()) + } + if fake.commitCalled { + t.Error("service must not be called on validation failure") + } + }) + } +} + +func TestCreateCommitErrors(t *testing.T) { + cases := []struct { + name string + commitErr error + wantStatus int + wantCode string + }{ + {"repo not found", reposervice.ErrRepositoryNotFound, http.StatusNotFound, "repository_not_found"}, + {"branch not found", reposervice.ErrRefNotFound, http.StatusNotFound, "ref_not_found"}, + {"delete target missing", reposervice.ErrPathNotFound, http.StatusNotFound, "path_not_found"}, + {"head mismatch", reposervice.ErrHeadMismatch, http.StatusConflict, "head_mismatch"}, + {"unknown blob", reposervice.ErrUnknownBlob, http.StatusUnprocessableEntity, "unknown_blob"}, + {"nothing to commit", reposervice.ErrNothingToCommit, http.StatusUnprocessableEntity, "nothing_to_commit"}, + {"delete target is a dir", reposervice.ErrNotAFile, http.StatusBadRequest, "invalid_request"}, + {"invalid branch", reposervice.ErrInvalidBranch, http.StatusBadRequest, "invalid_request"}, + {"invalid ops", reposervice.ErrInvalidCommitOps, http.StatusBadRequest, "invalid_request"}, + {"lfs not enabled", reposervice.ErrLFSNotEnabled, http.StatusBadRequest, "invalid_request"}, + {"internal", io.ErrUnexpectedEOF, http.StatusInternalServerError, "internal_error"}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + rec := httptest.NewRecorder() + newTestRouter(&fakeManager{commitErr: tc.commitErr}).ServeHTTP(rec, httptest.NewRequest(http.MethodPost, "/repositories/7/commits", strings.NewReader(validCommitBody()))) + + if rec.Code != tc.wantStatus { + t.Fatalf("status = %d, want %d: %s", rec.Code, tc.wantStatus, rec.Body.String()) + } + var body struct { + Error struct { + Code string `json:"code"` + } `json:"error"` + } + if err := json.Unmarshal(rec.Body.Bytes(), &body); err != nil { + t.Fatal(err) + } + if body.Error.Code != tc.wantCode { + t.Errorf("code = %q, want %q", body.Error.Code, tc.wantCode) + } + }) + } +} diff --git a/internal/server/control/repositories/types.go b/internal/server/control/repositories/types.go index 8e95aa4..b34d9b9 100644 --- a/internal/server/control/repositories/types.go +++ b/internal/server/control/repositories/types.go @@ -2,6 +2,7 @@ package repositories import ( "errors" + "fmt" "time" "github.com/Axenos-dev/HeadlessGit/internal/domain" @@ -115,3 +116,71 @@ type UploadBlobResponse struct { SHA string `json:"sha"` Size int64 `json:"size"` } + +type CommitAuthor struct { + Name string `json:"name"` + Email string `json:"email"` +} + +type CommitOperation struct { + Op string `json:"op"` // "put" | "delete" + Path string `json:"path"` + BlobSHA string `json:"blobSha,omitempty"` // puts only, from POST /blobs + Executable bool `json:"executable,omitempty"` // puts only +} + +type CreateCommitRequest struct { + Branch string `json:"branch"` + Message string `json:"message"` + Author CommitAuthor `json:"author"` + ExpectedHeadSHA string `json:"expectedHeadSha,omitempty"` + PusherID int64 `json:"pusherId,omitempty"` + Operations []CommitOperation `json:"operations"` +} + +func (r CreateCommitRequest) Validate() error { + if r.Branch == "" { + return errors.New("branch is required") + } + if r.Message == "" { + return errors.New("message is required") + } + if r.Author.Name == "" || r.Author.Email == "" { + return errors.New("author name and email are required") + } + if len(r.Operations) == 0 { + return errors.New("operations must not be empty") + } + for i, op := range r.Operations { + if op.Path == "" { + return fmt.Errorf("operations[%d]: path is required", i) + } + switch op.Op { + case "put": + if op.BlobSHA == "" { + return fmt.Errorf("operations[%d]: blobSha is required for put", i) + } + case "delete": + if op.BlobSHA != "" || op.Executable { + return fmt.Errorf("operations[%d]: delete takes no blobSha or executable", i) + } + default: + return fmt.Errorf("operations[%d]: op must be 'put' or 'delete'", i) + } + } + return nil +} + +type Commit struct { + Branch string `json:"branch"` + CommitSHA string `json:"commitSha"` + Before string `json:"before"` // the head the commit was built on +} + +func newCommit(res domain.CommitResult) Commit { + return Commit{ + Branch: res.Branch, + CommitSHA: res.CommitSHA, + Before: res.Before, + } +} diff --git a/internal/server/git/githttp/e2e_test.go b/internal/server/git/githttp/e2e_test.go index 754fbba..b44da75 100644 --- a/internal/server/git/githttp/e2e_test.go +++ b/internal/server/git/githttp/e2e_test.go @@ -45,7 +45,7 @@ func TestGitHTTPEndToEnd(t *testing.T) { t.Fatal(err) } - repoSvc := repositories.NewService(log, repositories.NewRegistry(database), backend, nil) + repoSvc := repositories.NewService(log, repositories.NewRegistry(database), backend, nil, nil) authSvc := auth.NewService(log, auth.NewRegistry(database)) permsSvc := permissions.NewService(permissions.NewRegistry(database)) usersSvc := users.NewService(users.NewRegistry(database)) diff --git a/internal/server/git/githttp/lfs_e2e_test.go b/internal/server/git/githttp/lfs_e2e_test.go index cf0b17e..874e9f2 100644 --- a/internal/server/git/githttp/lfs_e2e_test.go +++ b/internal/server/git/githttp/lfs_e2e_test.go @@ -63,7 +63,7 @@ func TestGitLFSEndToEnd(t *testing.T) { t.Fatal(err) } - repoSvc := repositories.NewService(log, repositories.NewRegistry(database), backend, nil) + repoSvc := repositories.NewService(log, repositories.NewRegistry(database), backend, nil, nil) authSvc := auth.NewService(log, auth.NewRegistry(database)) permsSvc := permissions.NewService(permissions.NewRegistry(database)) usersSvc := users.NewService(users.NewRegistry(database)) diff --git a/internal/server/response/codes.go b/internal/server/response/codes.go index 66f269b..705d852 100644 --- a/internal/server/response/codes.go +++ b/internal/server/response/codes.go @@ -13,4 +13,8 @@ const ( CodeRefNotFound = "ref_not_found" CodePathNotFound = "path_not_found" CodeLFSObjectNotFound = "lfs_object_not_found" + + CodeHeadMismatch = "head_mismatch" + CodeUnknownBlob = "unknown_blob" + CodeNothingToCommit = "nothing_to_commit" ) diff --git a/internal/services/lfs/service.go b/internal/services/lfs/service.go index acce6b7..8925f2f 100644 --- a/internal/services/lfs/service.go +++ b/internal/services/lfs/service.go @@ -242,6 +242,28 @@ func (s *Service) PutObject(ctx context.Context, repo domain.Repository, oid str return err } +// StoreObject registers and uploads a server-generated LFS object: used when +// api commits clean lfs-tracked files. Already verified objects are skipped +// without reading r, so callers must not rely on the reader being drained. +func (s *Service) StoreObject(ctx context.Context, repo domain.Repository, uploaderID int64, oid string, size int64, r io.Reader) error { + if err := validateOID(oid); err != nil { + return err + } + + // content addressing: an already stored and confirmed object is a no-op + if row, err := s.registry.GetLFSObject(ctx, repo.ID, oid); err == nil && row.Verified { + return nil + } + + // record the pending object; a conflicting existing row is fine + if _, err := s.registry.CreateLFSObject(ctx, uploaderID, repo.ID, oid, size); err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + + // PutObject streams to storage, verifies hash and size, and flips verified + return s.PutObject(ctx, repo, oid, size, r) +} + // {repo_id}/ab/cd/ func objectKey(repoID int64, oid string) string { return fmt.Sprintf("%d/%s/%s/%s", repoID, oid[0:2], oid[2:4], oid) diff --git a/internal/services/repositories/errors.go b/internal/services/repositories/errors.go index 7352ea8..c8f9fe4 100644 --- a/internal/services/repositories/errors.go +++ b/internal/services/repositories/errors.go @@ -17,4 +17,11 @@ var ( ErrNotAFile = errors.New("path is not a file") ErrLFSObjectNotFound = errors.New("lfs object not found") + + // api commits + ErrInvalidBranch = errors.New("invalid branch name") + ErrInvalidCommitOps = errors.New("invalid commit operations") + ErrHeadMismatch = errors.New("branch head mismatch") + ErrUnknownBlob = errors.New("blob not found in repository") + ErrNothingToCommit = errors.New("nothing to commit") ) diff --git a/internal/services/repositories/service.go b/internal/services/repositories/service.go index 4719854..835c448 100644 --- a/internal/services/repositories/service.go +++ b/internal/services/repositories/service.go @@ -3,7 +3,9 @@ package repositories import ( "bytes" "context" + "crypto/sha256" "database/sql" + "encoding/hex" "errors" "fmt" "io" @@ -36,10 +38,17 @@ type RepositoryStorage interface { StatBlob(ctx context.Context, storagePath, rev, treePath string) (gitbackend.BlobInfo, error) ReadBlob(ctx context.Context, storagePath, blobSHA string, out io.Writer) error WriteBlob(ctx context.Context, storagePath string, r io.Reader) (string, int64, error) + ApplyCommit(ctx context.Context, storagePath string, spec gitbackend.CommitSpec, ops []gitbackend.CommitOp, clean gitbackend.CleanFunc) (gitbackend.RefChange, error) } type LFSObjects interface { GetObject(ctx context.Context, repo domain.Repository, oid string) (io.ReadCloser, int64, error) + StoreObject(ctx context.Context, repo domain.Repository, uploaderID int64, oid string, size int64, r io.Reader) error +} + +// implemented by the webhooks service; nil disables push events for api commits +type PushDispatcher interface { + DispatchEvent(ctx context.Context, event domain.RepositoryEvent) error } type Service struct { @@ -47,14 +56,16 @@ type Service struct { registry Registry storage RepositoryStorage lfs LFSObjects + events PushDispatcher } -func NewService(logger *zap.Logger, registry Registry, storage RepositoryStorage, lfs LFSObjects) *Service { +func NewService(logger *zap.Logger, registry Registry, storage RepositoryStorage, lfs LFSObjects, events PushDispatcher) *Service { return &Service{ logger: logger, registry: registry, storage: storage, lfs: lfs, + events: events, } } @@ -350,6 +361,142 @@ func (s *Service) WriteBlob(ctx context.Context, repositoryID int64, in io.Reade return s.storage.WriteBlob(ctx, repo.StoragePath, in) } +func (s *Service) Commit(ctx context.Context, repositoryID int64, req domain.CommitRequest) (domain.CommitResult, error) { + repo, err := s.Get(ctx, repositoryID) + if err != nil { + return domain.CommitResult{}, err + } + + ops := make([]gitbackend.CommitOp, len(req.Operations)) + for i, op := range req.Operations { + mode := "" + if op.Executable { + mode = "100755" + } + ops[i] = gitbackend.CommitOp{ + Delete: op.Delete, + Path: op.Path, + BlobSHA: op.BlobSHA, + Mode: mode, + } + } + + spec := gitbackend.CommitSpec{ + Branch: req.Branch, + ExpectedOld: req.ExpectedHeadSHA, + Author: gitbackend.Identity{ + Name: req.Author.Name, + Email: req.Author.Email, + }, + Message: req.Message, + } + + // nil when LFS is disabled + // lfs-tracked paths then fail with ErrLFSRequired + var clean gitbackend.CleanFunc + if s.lfs != nil { + clean = s.lfsCleanFunc(ctx, repo, req.PusherID) + } + + change, err := s.storage.ApplyCommit(ctx, repo.StoragePath, spec, ops, clean) + switch { + case errors.Is(err, gitbackend.ErrInvalidBranch): + return domain.CommitResult{}, ErrInvalidBranch + case errors.Is(err, gitbackend.ErrInvalidOps), errors.Is(err, gitbackend.ErrInvalidPath), errors.Is(err, gitbackend.ErrInvalidRev): + return domain.CommitResult{}, fmt.Errorf("%w: %s", ErrInvalidCommitOps, err) + case errors.Is(err, gitbackend.ErrRevNotFound): + return domain.CommitResult{}, ErrRefNotFound + case errors.Is(err, gitbackend.ErrPathNotFound): + return domain.CommitResult{}, ErrPathNotFound + case errors.Is(err, gitbackend.ErrNotABlob): + return domain.CommitResult{}, ErrNotAFile + case errors.Is(err, gitbackend.ErrHeadMismatch): + return domain.CommitResult{}, ErrHeadMismatch + case errors.Is(err, gitbackend.ErrUnknownBlob): + return domain.CommitResult{}, ErrUnknownBlob + case errors.Is(err, gitbackend.ErrNothingToCommit): + return domain.CommitResult{}, ErrNothingToCommit + case errors.Is(err, gitbackend.ErrLFSRequired): + return domain.CommitResult{}, ErrLFSNotEnabled + case err != nil: + return domain.CommitResult{}, err + } + + s.dispatchPush(ctx, repo, req, change) + + return domain.CommitResult{ + Branch: req.Branch, + CommitSHA: change.NewSHA, + Before: change.OldSHA, + }, nil +} + +func (s *Service) lfsCleanFunc(ctx context.Context, repo domain.Repository, pusherID int64) gitbackend.CleanFunc { + uploaderID := pusherID + if uploaderID == 0 { + uploaderID = repo.OwnerID + } + + return func(path, blobSHA string, size int64) (string, error) { + // check if blob is already LFS pointer + if size <= domain.LFSPointerMaxSize { + var buf bytes.Buffer + if err := s.storage.ReadBlob(ctx, repo.StoragePath, blobSHA, &buf); err != nil { + return "", err + } + if _, ok := domain.ParseLFSPointer(buf.Bytes()); ok { + return blobSHA, nil + } + } + + // hash the local blob to get the lfs oid + hasher := sha256.New() + if err := s.storage.ReadBlob(ctx, repo.StoragePath, blobSHA, hasher); err != nil { + return "", err + } + oid := hex.EncodeToString(hasher.Sum(nil)) + + // stream the same blob into lfs storage + pr, pw := io.Pipe() + go func() { + pw.CloseWithError(s.storage.ReadBlob(ctx, repo.StoragePath, blobSHA, pw)) + }() + err := s.lfs.StoreObject(ctx, repo, uploaderID, oid, size, pr) + pr.Close() // unblocks the writer when StoreObject returned without draining + if err != nil { + return "", err + } + + // construct pointer by "hands" + pointer := fmt.Sprintf("version https://git-lfs.github.com/spec/v1\noid sha256:%s\nsize %d\n", oid, size) + pointerSHA, _, err := s.storage.WriteBlob(ctx, repo.StoragePath, strings.NewReader(pointer)) + return pointerSHA, err + } +} + +// dispatch webhook event +func (s *Service) dispatchPush(ctx context.Context, repo domain.Repository, req domain.CommitRequest, change gitbackend.RefChange) { + if s.events == nil { + return + } + + err := s.events.DispatchEvent(ctx, domain.RepositoryEvent{ + Event: "push", + RepositoryID: repo.ID, + RepositoryName: repo.RepositoryName, + RepositoryFullName: fmt.Sprintf("%d/%s", repo.OwnerID, repo.RepositoryName), + PusherID: req.PusherID, + PusherUsername: req.Author.Name, + Ref: change.Ref, + OldSHA: change.OldSHA, + NewSHA: change.NewSHA, + Timestamp: time.Now().UTC(), + }) + if err != nil { + s.logger.Warn("failed to enqueue webhook event", zap.String("ref", change.Ref), zap.Error(err)) + } +} + func toDomain(r gen.Repository) domain.Repository { repo := domain.Repository{ ID: r.ID, diff --git a/internal/services/repositories/service_test.go b/internal/services/repositories/service_test.go index de0a32b..ac9239f 100644 --- a/internal/services/repositories/service_test.go +++ b/internal/services/repositories/service_test.go @@ -5,6 +5,7 @@ import ( "archive/zip" "bytes" "context" + "crypto/sha256" "database/sql" "errors" "fmt" @@ -39,6 +40,12 @@ type fakeStorage struct { blobInfo gitbackend.BlobInfo blobStatErr error blobContent string + + writeBlobSHA string + applyChange gitbackend.RefChange + applyErr error + // optional hook to inspect (and exercise) what ApplyCommit received + applyFn func(spec gitbackend.CommitSpec, ops []gitbackend.CommitOp, clean gitbackend.CleanFunc) error } func (f fakeStorage) ResolveCommit(ctx context.Context, storagePath, rev string) (string, error) { @@ -67,8 +74,29 @@ func (f fakeStorage) ReadBlob(ctx context.Context, storagePath, blobSHA string, return err } +func (f fakeStorage) WriteBlob(ctx context.Context, storagePath string, r io.Reader) (string, int64, error) { + n, err := io.Copy(io.Discard, r) + if err != nil { + return "", 0, err + } + return f.writeBlobSHA, n, nil +} + +func (f fakeStorage) ApplyCommit(ctx context.Context, storagePath string, spec gitbackend.CommitSpec, ops []gitbackend.CommitOp, clean gitbackend.CleanFunc) (gitbackend.RefChange, error) { + if f.applyFn != nil { + if err := f.applyFn(spec, ops, clean); err != nil { + return gitbackend.RefChange{}, err + } + } + if f.applyErr != nil { + return gitbackend.RefChange{}, f.applyErr + } + return f.applyChange, nil +} + type fakeLFS struct { objects map[string]string // oid -> content + stored map[string]string // oid -> content received via StoreObject } func (f fakeLFS) GetObject(ctx context.Context, repo domain.Repository, oid string) (io.ReadCloser, int64, error) { @@ -79,6 +107,26 @@ func (f fakeLFS) GetObject(ctx context.Context, repo domain.Repository, oid stri return io.NopCloser(strings.NewReader(content)), int64(len(content)), nil } +func (f fakeLFS) StoreObject(ctx context.Context, repo domain.Repository, uploaderID int64, oid string, size int64, r io.Reader) error { + body, err := io.ReadAll(r) + if err != nil { + return err + } + if f.stored != nil { + f.stored[oid] = string(body) + } + return nil +} + +type fakeDispatcher struct { + events *[]domain.RepositoryEvent +} + +func (f fakeDispatcher) DispatchEvent(ctx context.Context, event domain.RepositoryEvent) error { + *f.events = append(*f.events, event) + return nil +} + func TestPrepareArchive(t *testing.T) { row := gen.Repository{ID: 7, RepositoryName: "myrepo", StoragePath: "7/myrepo.git", Visibility: "private"} @@ -102,7 +150,7 @@ func TestPrepareArchive(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - svc := NewService(zap.NewNop(), tc.registry, tc.storage, tc.lfs) + svc := NewService(zap.NewNop(), tc.registry, tc.storage, tc.lfs, nil) req, err := svc.PrepareArchive(context.Background(), row.ID, "main", tc.format, tc.includeLFS) if !errors.Is(err, tc.wantErr) { t.Fatalf("PrepareArchive error = %v, want %v", err, tc.wantErr) @@ -146,6 +194,7 @@ func TestStreamArchiveSmudgesLFS(t *testing.T) { fakeRegistry{}, fakeStorage{sha: testSHA, tarBytes: tarBuf.Bytes()}, fakeLFS{objects: map[string]string{oid: content}}, + nil, ) req := domain.ArchiveRequest{ @@ -203,7 +252,7 @@ func TestPrepareBlob(t *testing.T) { pointer := fmt.Sprintf("version https://git-lfs.github.com/spec/v1\noid sha256:%s\nsize %d\n", oid, len(content)) t.Run("raw file", func(t *testing.T) { - svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage("hello\n"), nil) + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage("hello\n"), nil, nil) req, err := svc.PrepareBlob(context.Background(), row.ID, "main", "README.md", false) if err != nil { t.Fatal(err) @@ -214,7 +263,7 @@ func TestPrepareBlob(t *testing.T) { }) t.Run("pointer smudged", func(t *testing.T) { - svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage(pointer), fakeLFS{objects: map[string]string{oid: content}}) + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage(pointer), fakeLFS{objects: map[string]string{oid: content}}, nil) req, err := svc.PrepareBlob(context.Background(), row.ID, "main", "big.bin", true) if err != nil { t.Fatal(err) @@ -228,7 +277,7 @@ func TestPrepareBlob(t *testing.T) { }) t.Run("pointer without lfs flag stays raw", func(t *testing.T) { - svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage(pointer), fakeLFS{objects: map[string]string{oid: content}}) + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage(pointer), fakeLFS{objects: map[string]string{oid: content}}, nil) req, err := svc.PrepareBlob(context.Background(), row.ID, "main", "big.bin", false) if err != nil { t.Fatal(err) @@ -241,7 +290,7 @@ func TestPrepareBlob(t *testing.T) { t.Run("large blob is never sniffed", func(t *testing.T) { st := blobStorage(pointer) st.blobInfo.Size = 5000 // over the pointer cap, content must not be read - svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, st, fakeLFS{}) + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, st, fakeLFS{}, nil) req, err := svc.PrepareBlob(context.Background(), row.ID, "main", "big.bin", true) if err != nil { t.Fatal(err) @@ -252,7 +301,7 @@ func TestPrepareBlob(t *testing.T) { }) t.Run("missing lfs object fails loudly", func(t *testing.T) { - svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage(pointer), fakeLFS{}) + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, blobStorage(pointer), fakeLFS{}, nil) if _, err := svc.PrepareBlob(context.Background(), row.ID, "main", "big.bin", true); !errors.Is(err, ErrLFSObjectNotFound) { t.Errorf("want ErrLFSObjectNotFound, got %v", err) } @@ -274,7 +323,7 @@ func TestPrepareBlob(t *testing.T) { } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, tc.storage, tc.lfs) + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, tc.storage, tc.lfs, nil) if _, err := svc.PrepareBlob(context.Background(), row.ID, "main", "x", tc.includeLFS); !errors.Is(err, tc.wantErr) { t.Errorf("PrepareBlob error = %v, want %v", err, tc.wantErr) } @@ -289,7 +338,7 @@ func TestStreamBlob(t *testing.T) { repo := domain.Repository{ID: 7, RepositoryName: "myrepo", StoragePath: "7/myrepo.git"} t.Run("raw", func(t *testing.T) { - svc := NewService(zap.NewNop(), fakeRegistry{}, blobStorage("hello\n"), nil) + svc := NewService(zap.NewNop(), fakeRegistry{}, blobStorage("hello\n"), nil, nil) var out bytes.Buffer if err := svc.StreamBlob(context.Background(), domain.BlobRequest{Repository: repo, BlobSHA: blobSHA}, &out); err != nil { t.Fatal(err) @@ -300,7 +349,7 @@ func TestStreamBlob(t *testing.T) { }) t.Run("smudged", func(t *testing.T) { - svc := NewService(zap.NewNop(), fakeRegistry{}, blobStorage(""), fakeLFS{objects: map[string]string{oid: content}}) + svc := NewService(zap.NewNop(), fakeRegistry{}, blobStorage(""), fakeLFS{objects: map[string]string{oid: content}}, nil) var out bytes.Buffer if err := svc.StreamBlob(context.Background(), domain.BlobRequest{Repository: repo, BlobSHA: blobSHA, LFSOID: oid}, &out); err != nil { t.Fatal(err) @@ -310,3 +359,167 @@ func TestStreamBlob(t *testing.T) { } }) } + +func TestCommit(t *testing.T) { + row := gen.Repository{ID: 7, OwnerID: 3, RepositoryName: "myrepo", StoragePath: "7/myrepo.git", Visibility: "private"} + change := gitbackend.RefChange{Ref: "refs/heads/main", OldSHA: strings.Repeat("a", 40), NewSHA: testSHA} + req := domain.CommitRequest{ + Branch: "main", + Message: "update", + Author: domain.CommitIdentity{Name: "api-user", Email: "api@test"}, + ExpectedHeadSHA: strings.Repeat("a", 40), + PusherID: 42, + Operations: []domain.CommitFileOp{ + {Path: "run.sh", BlobSHA: blobSHA, Executable: true}, + {Path: "old.txt", Delete: true}, + }, + } + + t.Run("maps ops and dispatches the push event", func(t *testing.T) { + var events []domain.RepositoryEvent + var gotSpec gitbackend.CommitSpec + var gotOps []gitbackend.CommitOp + var gotClean gitbackend.CleanFunc + st := fakeStorage{applyChange: change, applyFn: func(spec gitbackend.CommitSpec, ops []gitbackend.CommitOp, clean gitbackend.CleanFunc) error { + gotSpec, gotOps, gotClean = spec, ops, clean + return nil + }} + + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, st, fakeLFS{}, fakeDispatcher{events: &events}) + res, err := svc.Commit(context.Background(), row.ID, req) + if err != nil { + t.Fatal(err) + } + + if res.CommitSHA != testSHA || res.Before != change.OldSHA || res.Branch != "main" { + t.Errorf("result = %+v", res) + } + if gotSpec.Branch != "main" || gotSpec.ExpectedOld != req.ExpectedHeadSHA || gotSpec.Author.Name != "api-user" { + t.Errorf("spec = %+v", gotSpec) + } + if len(gotOps) != 2 || gotOps[0].Mode != "100755" || !gotOps[1].Delete { + t.Errorf("ops = %+v", gotOps) + } + if gotClean == nil { + t.Error("clean must be set when lfs is enabled") + } + + if len(events) != 1 { + t.Fatalf("events = %+v", events) + } + e := events[0] + if e.Event != "push" || e.RepositoryFullName != "3/myrepo" || e.PusherID != 42 || + e.PusherUsername != "api-user" || e.Ref != change.Ref || e.OldSHA != change.OldSHA || e.NewSHA != change.NewSHA { + t.Errorf("event = %+v", e) + } + }) + + t.Run("nil clean when lfs disabled", func(t *testing.T) { + st := fakeStorage{applyChange: change, applyFn: func(_ gitbackend.CommitSpec, _ []gitbackend.CommitOp, clean gitbackend.CleanFunc) error { + if clean != nil { + t.Error("clean must be nil when lfs is disabled") + } + return nil + }} + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, st, nil, nil) + if _, err := svc.Commit(context.Background(), row.ID, req); err != nil { + t.Fatal(err) + } + }) + + t.Run("error mapping and no event on failure", func(t *testing.T) { + cases := []struct { + backend error + want error + }{ + {gitbackend.ErrInvalidBranch, ErrInvalidBranch}, + {gitbackend.ErrInvalidOps, ErrInvalidCommitOps}, + {gitbackend.ErrRevNotFound, ErrRefNotFound}, + {gitbackend.ErrPathNotFound, ErrPathNotFound}, + {gitbackend.ErrNotABlob, ErrNotAFile}, + {gitbackend.ErrHeadMismatch, ErrHeadMismatch}, + {gitbackend.ErrUnknownBlob, ErrUnknownBlob}, + {gitbackend.ErrNothingToCommit, ErrNothingToCommit}, + {gitbackend.ErrLFSRequired, ErrLFSNotEnabled}, + } + for _, tc := range cases { + var events []domain.RepositoryEvent + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, fakeStorage{applyErr: tc.backend}, nil, fakeDispatcher{events: &events}) + if _, err := svc.Commit(context.Background(), row.ID, req); !errors.Is(err, tc.want) { + t.Errorf("backend %v: got %v, want %v", tc.backend, err, tc.want) + } + if len(events) != 0 { + t.Errorf("backend %v: event dispatched on failure", tc.backend) + } + } + }) +} + +func TestCommitCleanClosure(t *testing.T) { + row := gen.Repository{ID: 7, OwnerID: 3, RepositoryName: "myrepo", StoragePath: "7/myrepo.git", Visibility: "private"} + pointerBlob := strings.Repeat("f", 40) + req := domain.CommitRequest{ + Branch: "main", + Message: "x", + Author: domain.CommitIdentity{Name: "t", Email: "t@t"}, + Operations: []domain.CommitFileOp{ + {Path: "big.bin", BlobSHA: blobSHA}, + }, + } + + t.Run("converts payload to lfs object and pointer", func(t *testing.T) { + payload := "REAL BINARY PAYLOAD" + wantOID := fmt.Sprintf("%x", sha256.Sum256([]byte(payload))) + + stored := map[string]string{} + st := fakeStorage{ + blobContent: payload, + writeBlobSHA: pointerBlob, + applyFn: func(_ gitbackend.CommitSpec, _ []gitbackend.CommitOp, clean gitbackend.CleanFunc) error { + got, err := clean("big.bin", blobSHA, int64(len(payload))) + if err != nil { + return err + } + if got != pointerBlob { + t.Errorf("clean returned %q, want pointer blob %q", got, pointerBlob) + } + return nil + }, + } + + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, st, fakeLFS{stored: stored}, nil) + if _, err := svc.Commit(context.Background(), row.ID, req); err != nil { + t.Fatal(err) + } + if stored[wantOID] != payload { + t.Errorf("stored objects = %v, want oid %s with payload", stored, wantOID) + } + }) + + t.Run("existing pointer passes through untouched", func(t *testing.T) { + pointer := "version https://git-lfs.github.com/spec/v1\noid sha256:" + strings.Repeat("ab", 32) + "\nsize 44\n" + + stored := map[string]string{} + st := fakeStorage{ + blobContent: pointer, + applyFn: func(_ gitbackend.CommitSpec, _ []gitbackend.CommitOp, clean gitbackend.CleanFunc) error { + got, err := clean("big.bin", blobSHA, int64(len(pointer))) + if err != nil { + return err + } + if got != blobSHA { + t.Errorf("clean returned %q, want passthrough %q", got, blobSHA) + } + return nil + }, + } + + svc := NewService(zap.NewNop(), fakeRegistry{repo: row}, st, fakeLFS{stored: stored}, nil) + if _, err := svc.Commit(context.Background(), row.ID, req); err != nil { + t.Fatal(err) + } + if len(stored) != 0 { + t.Errorf("pointer passthrough must not store objects, got %v", stored) + } + }) +} From 8da51637e3e7bb1eec3f7c53f95283c0585762de Mon Sep 17 00:00:00 2001 From: Axenos-dev Date: Mon, 6 Jul 2026 12:20:14 -0700 Subject: [PATCH 6/7] GC for repos to clean orphaned blobs in ODB --- .env.example | 7 +++ internal/config/config.go | 7 +++ internal/db/gen/repositories.sql.go | 35 +++++++++++++++ internal/db/queries/repositories.sql | 3 ++ internal/gitbackend/backend.go | 1 + internal/gitbackend/local.go | 21 +++++++++ internal/gitbackend/local_test.go | 51 ++++++++++++++++++++++ internal/server/server.go | 20 +++++---- internal/services/repositories/registry.go | 4 ++ internal/services/repositories/service.go | 33 ++++++++++++++ 10 files changed, 173 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index 9a2ea87..674369f 100644 --- a/.env.example +++ b/.env.example @@ -15,6 +15,13 @@ REPO_ROOT=data/repos # where the host key file is kept (for ssh) SSH_HOST_KEY_PATH=data/ssh/host_ed25519 +# background maintenance intervals (go duration syntax, e.g. "30m", "12h") +# a zero duration ("0") disables the loop +TOKEN_GC_INTERVAL=1h +REPO_GC_INTERVAL=5h +# goroutines delivering webhook events +WEBHOOK_WORKERS=3 + # enable the LFS endpoints (batch + verify + object transfer) LFS_ENABLED=false diff --git a/internal/config/config.go b/internal/config/config.go index 202bca7..6333ab8 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -3,6 +3,7 @@ package config import ( "fmt" "strings" + "time" "github.com/caarlos0/env/v11" ) @@ -18,6 +19,12 @@ type ServerConfig struct { GitSSHPort int `env:"GIT_SSH_PORT" envDefault:"2222"` RepoRoot string `env:"REPO_ROOT" envDefault:"data/repos"` HostKeyPath string `env:"SSH_HOST_KEY_PATH" envDefault:"data/ssh/host_ed25519"` + + // background maintenance, + // a zero duration disables the loop + TokenGCInterval time.Duration `env:"TOKEN_GC_INTERVAL" envDefault:"1h"` + RepoGCInterval time.Duration `env:"REPO_GC_INTERVAL" envDefault:"5h"` + WebhookWorkers int `env:"WEBHOOK_WORKERS" envDefault:"3"` } type LFSConfig struct { diff --git a/internal/db/gen/repositories.sql.go b/internal/db/gen/repositories.sql.go index 5915b50..5fe79d7 100644 --- a/internal/db/gen/repositories.sql.go +++ b/internal/db/gen/repositories.sql.go @@ -101,6 +101,41 @@ func (q *Queries) GetRepositoryByPath(ctx context.Context, arg GetRepositoryByPa return i, err } +const listRepositories = `-- name: ListRepositories :many +select id, owner_id, repository_name, storage_path, visibility, created_at_unix_ms, updated_at_unix_ms from repositories +` + +func (q *Queries) ListRepositories(ctx context.Context) ([]Repository, error) { + rows, err := q.db.QueryContext(ctx, listRepositories) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Repository + for rows.Next() { + var i Repository + if err := rows.Scan( + &i.ID, + &i.OwnerID, + &i.RepositoryName, + &i.StoragePath, + &i.Visibility, + &i.CreatedAtUnixMs, + &i.UpdatedAtUnixMs, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const listUserRepositories = `-- name: ListUserRepositories :many select id, owner_id, repository_name, storage_path, visibility, created_at_unix_ms, updated_at_unix_ms from repositories where owner_id=? diff --git a/internal/db/queries/repositories.sql b/internal/db/queries/repositories.sql index c617127..e53e3b0 100644 --- a/internal/db/queries/repositories.sql +++ b/internal/db/queries/repositories.sql @@ -6,6 +6,9 @@ where id=? limit 1; select * from repositories where owner_id=?; +-- name: ListRepositories :many +select * from repositories; + -- name: CreateRepository :one insert into repositories ( owner_id, repository_name, storage_path, visibility diff --git a/internal/gitbackend/backend.go b/internal/gitbackend/backend.go index 6850b98..56e49cf 100644 --- a/internal/gitbackend/backend.go +++ b/internal/gitbackend/backend.go @@ -19,4 +19,5 @@ type Backend interface { ReadBlob(ctx context.Context, storagePath, blobSHA string, out io.Writer) error WriteBlob(ctx context.Context, storagePath string, r io.Reader) (string, int64, error) ApplyCommit(ctx context.Context, storagePath string, spec CommitSpec, ops []CommitOp, clean CleanFunc) (RefChange, error) + GC(ctx context.Context, storagePath string) error } diff --git a/internal/gitbackend/local.go b/internal/gitbackend/local.go index 0be0e22..e1cf9fd 100644 --- a/internal/gitbackend/local.go +++ b/internal/gitbackend/local.go @@ -25,6 +25,9 @@ const ( ReceivePack // push ) +// repacking a large repo can take a while +const gcTimeout = 30 * time.Minute + // returns the command name of the service func (s Service) Name() string { if s == ReceivePack { @@ -355,6 +358,24 @@ func (l *Local) WriteBlob(ctx context.Context, storagePath string, r io.Reader) return strings.TrimSpace(out.String()), counter.n, nil } +func (l *Local) GC(ctx context.Context, storagePath string) error { + dir, err := l.resolve(storagePath) + if err != nil { + return err + } + + ctx, cancel := context.WithTimeout(ctx, gcTimeout) + defer cancel() + + cmd := exec.CommandContext(ctx, l.gitPath, "-C", dir, "gc", "--quiet") + var stderr bytes.Buffer + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return fmt.Errorf("git gc: %w: %s", err, strings.TrimSpace(stderr.String())) + } + return nil +} + // creates a commit on a branch from already-uploaded blobs func (l *Local) ApplyCommit(ctx context.Context, storagePath string, spec CommitSpec, ops []CommitOp, clean CleanFunc) (RefChange, error) { dir, err := l.resolve(storagePath) diff --git a/internal/gitbackend/local_test.go b/internal/gitbackend/local_test.go index 2c88959..7dc6b77 100644 --- a/internal/gitbackend/local_test.go +++ b/internal/gitbackend/local_test.go @@ -13,6 +13,7 @@ import ( "sort" "strings" "testing" + "time" ) // runs a git command in dir with a deterministic identity, failing the test on error @@ -656,6 +657,56 @@ func TestApplyCommit(t *testing.T) { }) } +func TestGC(t *testing.T) { + if _, err := exec.LookPath("git"); err != nil { + t.Skip("git not on PATH") + } + + root := t.TempDir() + l, err := NewLocal(root) + if err != nil { + t.Fatal(err) + } + ctx := context.Background() + const repo = "1/test.git" + + if err := l.InitBare(ctx, repo); err != nil { + t.Fatal(err) + } + + // a fresh orphan must survive gc: the prune grace period protects + // uploads whose commit has not happened yet + fresh, _, err := l.WriteBlob(ctx, repo, strings.NewReader("pending upload\n")) + if err != nil { + t.Fatal(err) + } + if err := l.GC(ctx, repo); err != nil { + t.Fatal(err) + } + if err := l.ReadBlob(ctx, repo, fresh, io.Discard); err != nil { + t.Fatalf("fresh orphan pruned: %v", err) + } + + // an orphan backdated past gc.pruneExpire (2 weeks) must be pruned; + // backdate before gc runs, since gc moves loose objects into cruft packs + orphan, _, err := l.WriteBlob(ctx, repo, strings.NewReader("abandoned upload\n")) + if err != nil { + t.Fatal(err) + } + loose := filepath.Join(root, repo, "objects", orphan[:2], orphan[2:]) + old := time.Now().Add(-21 * 24 * time.Hour) + if err := os.Chtimes(loose, old, old); err != nil { + t.Fatal(err) + } + + if err := l.GC(ctx, repo); err != nil { + t.Fatal(err) + } + if err := l.ReadBlob(ctx, repo, orphan, io.Discard); err == nil { + t.Error("expired orphan survived gc") + } +} + func TestDiffRefs(t *testing.T) { cases := []struct { name string diff --git a/internal/server/server.go b/internal/server/server.go index d1d0279..8fdbe6a 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -3,7 +3,6 @@ package server import ( "context" "fmt" - "time" "github.com/Axenos-dev/HeadlessGit/internal/config" "github.com/Axenos-dev/HeadlessGit/internal/db" @@ -31,18 +30,13 @@ type Services struct { DB *db.DB } -// clean up expired tokens every hour -const tokenGCInterval = time.Hour - -// number of workers which going to handle webhooks -const webhookWorkers = 3 - type server struct { cfg config.ServerConfig logger *zap.Logger auth *authservice.Service webhooks *webhooksservice.Service + repos *reposervice.Service control *control.Server git *git.Server @@ -58,6 +52,7 @@ func NewServer( logger: logger, auth: svc.Authentication, webhooks: svc.Webhooks, + repos: svc.Repositories, control: control.NewServer(logger.With(zap.String("component", "control")), control.Services{ Repositories: svc.Repositories, Authentication: svc.Authentication, @@ -81,11 +76,18 @@ func (s *server) Run(ctx context.Context) error { errCh := make(chan error, 3) // clean up expired tokens - go s.auth.RunExpiredTokenGC(ctx, tokenGCInterval) + if s.cfg.TokenGCInterval > 0 { + go s.auth.RunExpiredTokenGC(ctx, s.cfg.TokenGCInterval) + } + + // run git GC, to remove orphaned blobs in OBD + if s.cfg.RepoGCInterval > 0 { + go s.repos.StartGC(ctx, s.cfg.RepoGCInterval) + } // handle webhooks // it runs N goroutines for us, so dont Start in goroutine - s.webhooks.Start(ctx, webhookWorkers) + s.webhooks.Start(ctx, s.cfg.WebhookWorkers) go func() { errCh <- s.control.Run(ctx, fmt.Sprintf(":%d", s.cfg.ControlPort)) diff --git a/internal/services/repositories/registry.go b/internal/services/repositories/registry.go index 01192a2..a92448b 100644 --- a/internal/services/repositories/registry.go +++ b/internal/services/repositories/registry.go @@ -36,6 +36,10 @@ func (r *RepositoryRegistry) ListUserRepositories(ctx context.Context, ownerID i return r.db.ListUserRepositories(ctx, ownerID) } +func (r *RepositoryRegistry) ListRepositories(ctx context.Context) ([]gen.Repository, error) { + return r.db.ListRepositories(ctx) +} + func (r *RepositoryRegistry) CreateRepository(ctx context.Context, ownerID int64, name, storagePath, visibility string) (gen.Repository, error) { return r.db.CreateRepository(ctx, gen.CreateRepositoryParams{ OwnerID: ownerID, diff --git a/internal/services/repositories/service.go b/internal/services/repositories/service.go index 835c448..4ac759c 100644 --- a/internal/services/repositories/service.go +++ b/internal/services/repositories/service.go @@ -27,6 +27,7 @@ type Registry interface { GetRepositoryByPath(ctx context.Context, namespace, name string) (gen.Repository, error) UpdateRepositoryVisibility(ctx context.Context, repositoryID int64, visibility string) (gen.Repository, error) ListUserRepositories(ctx context.Context, ownerID int64) ([]gen.Repository, error) + ListRepositories(ctx context.Context) ([]gen.Repository, error) } type RepositoryStorage interface { @@ -39,6 +40,7 @@ type RepositoryStorage interface { ReadBlob(ctx context.Context, storagePath, blobSHA string, out io.Writer) error WriteBlob(ctx context.Context, storagePath string, r io.Reader) (string, int64, error) ApplyCommit(ctx context.Context, storagePath string, spec gitbackend.CommitSpec, ops []gitbackend.CommitOp, clean gitbackend.CleanFunc) (gitbackend.RefChange, error) + GC(ctx context.Context, storagePath string) error } type LFSObjects interface { @@ -69,6 +71,37 @@ func NewService(logger *zap.Logger, registry Registry, storage RepositoryStorage } } +func (s *Service) StartGC(ctx context.Context, interval time.Duration) { + ticker := time.NewTicker(interval) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + } + + repos, err := s.registry.ListRepositories(ctx) + if err != nil { + s.logger.Error("gc: failed to list repositories", zap.Error(err)) + continue + } + + for _, repo := range repos { + if err := s.storage.GC(ctx, repo.StoragePath); err != nil { + s.logger.Warn("gc failed", zap.Int64("repository_id", repo.ID), zap.Error(err)) + } + + // pace the sweep so gc never hammers the whole disk at once + select { + case <-ctx.Done(): + return + case <-time.After(time.Second): + } + } + } +} + func (s *Service) Get(ctx context.Context, repositoryID int64) (domain.Repository, error) { repo, err := s.registry.GetRepository(ctx, repositoryID) if errors.Is(err, sql.ErrNoRows) { From 4759639a1339c97b2e1b096c384091a10b1463b3 Mon Sep 17 00:00:00 2001 From: Axenos-dev Date: Mon, 6 Jul 2026 13:51:44 -0700 Subject: [PATCH 7/7] Updated README for contents api --- README.md | 103 ++++++++++++++++++++++++++++- images/{achive.png => archive.png} | Bin images/commit.png | Bin 0 -> 367358 bytes 3 files changed, 101 insertions(+), 2 deletions(-) rename images/{achive.png => archive.png} (100%) create mode 100644 images/commit.png diff --git a/README.md b/README.md index 523396e..333ac1a 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,9 @@ Basically, this is a Git layer of infrastructure you'd put _underneath_ a projec - Basic Git over **SSH** and **HTTP** for clone / fetch / push. - **Git LFS** for large files, with object storage on local disk or any S3-compatible bucket (AWS S3, Cloudflare R2, MinIO). - A small **control API**, RESTful api to manage repositories, users, SSH keys, tokens, and permissions. +- A **repo content API** — list trees, read files, download zip/tar.gz archives, and create commits over REST, so your backend never needs a local clone. - Simple **permission model** (`read` / `write` / `admin`) enforced before every Git operation. -- **Push webhooks** — signed deliveries on every successful push. +- **Push webhooks** — signed deliveries on every ref change, pushed or committed via the API. - Bare-repository storage on a filesystem, with SQLite for metadata. ## Example @@ -78,6 +79,9 @@ All configuration is via environment variables. | `REPO_ROOT` | `data/repos` | Where bare repositories are stored. | | `SSH_HOST_KEY_PATH` | `data/ssh/host_ed25519` | SSH host key file (generated on first boot if absent). | | `ADMIN_TOKEN` | _(empty)_ | Raw token for the seeded admin account. Only its hash is stored. Empty = no admin seeded. | +| `TOKEN_GC_INTERVAL` | `1h` | How often expired tokens are deleted. `0` disables the loop. | +| `REPO_GC_INTERVAL` | `5h` | How often `git gc` sweeps the repositories (repack + prune). `0` disables the loop. | +| `WEBHOOK_WORKERS` | `3` | Goroutines delivering webhook events. | See [`.env.example`](.env.example). @@ -138,13 +142,108 @@ Every request requires `Authorization: Bearer `. Responses are enve | `POST` | `/repositories/{id}/webhooks` | `{url}` | Register a push webhook; the signing secret is returned **once**. | | `DELETE` | `/repositories/{id}/webhooks/{hookId}` | — | Delete a webhook. | +**Repository contents & commits** + +| Method | Path | Body | Description | +| ------ | ---------------------------------------------- | ----------- | ---------------------------------------------------------------------- | +| `GET` | `/repositories/{id}/contents?ref=&path=` | — | List one directory level of the tree at a ref. | +| `GET` | `/repositories/{id}/blob?ref=&path=&lfs=` | — | Stream one file's raw content. | +| `GET` | `/repositories/{id}/archive?ref=&format=&lfs=` | — | Stream a `zip` (default) or `tar.gz` archive of the tree. | +| `POST` | `/repositories/{id}/blobs` | _raw bytes_ | Upload content into the repo's object database; returns `{sha, size}`. | +| `POST` | `/repositories/{id}/commits` | JSON | Create a commit on a branch from uploaded blobs. | + +### Reading a repository + +`ref` accepts anything git can resolve to a commit — a branch, tag, sha, or expression like `main~2` — and defaults to `HEAD`. Every response is pinned to the exact commit it was answered from, so consumers can page through a repository without seeing a torn view mid-push. + +`GET /contents` returns the entries of one directory level: + +```json +{ + "data": { + "ref": "main", + "sha": "9fb037999f264ba9a7fc6274d15fa3ae2ab98312", + "path": "src", + "entries": [ + { + "name": "main.go", + "path": "src/main.go", + "type": "file", + "mode": "100644", + "size": 1234, + "sha": "..." + }, + { + "name": "vendor", + "path": "src/vendor", + "type": "dir", + "mode": "040000", + "sha": "..." + } + ] + } +} +``` + +`type` is `file` | `dir` | `symlink` | `submodule`. Listings over 10k entries set `"truncated": true`. + +`GET /blob` streams the file bytes with `Content-Length`, a strong `ETag` (the blob sha — content-addressed, so `If-None-Match` caching works perfectly), and `X-HeadlessGit-Commit` carrying the resolved commit. With `lfs=true`, an LFS pointer file is replaced by the real object; a missing object is a `404` rather than silently serving the pointer. + +`GET /archive` streams the whole tree as an artifact, named `-.zip` with a matching top-level folder. With `lfs=true`, pointer files are swapped for the real objects **in-flight** — the archive is re-encoded entry by entry, nothing is buffered or written to disk: + +![archive](images/archive.png) + +A pointer whose object is missing stays a pointer. + +### Writing without a clone + +Commits follow two-step model: upload content first, then commit metadata referencing it. + +![commit](images/commit.png) + +```sh +# 1. upload each new/changed file's bytes (raw body, streamed) +curl -H "Authorization: Bearer $TOKEN" \ + --data-binary @config.yaml \ + http://localhost:4001/repositories/7/blobs +# -> {"data": {"sha": "44b4fc6d...", "size": 812}} + +# 2. create the commit (atomic, any number of operations) +curl -H "Authorization: Bearer $TOKEN" -X POST \ + http://localhost:4001/repositories/7/commits -d '{ + "branch": "main", + "message": "update config", + "author": { "name": "deploy-bot", "email": "bot@example.com" }, + "expectedHeadSha": "9fb03799...", + "operations": [ + { "op": "put", "path": "config.yaml", "blobSha": "44b4fc6d..." }, + { "op": "delete", "path": "config.old.yaml" } + ] + }' +# -> 201 {"data": {"branch": "main", "commitSha": "...", "before": "9fb03799..."}} +``` + +`expectedHeadSha` controls concurrency: + +| Value | Meaning | +| ---------------- | ---------------------------------------------------------------------------------------- | +| _(omitted)_ | Last write wins. | +| a commit sha | Compare-and-swap: `409 head_mismatch` if the branch moved. | +| the all-zero sha | The branch must not exist yet — creates it (or the first commit on an empty repository). | + +Content is deduplicated by sha, so retrying an upload is free and a lost `409` race can be retried without re-uploading anything. Blobs that never get committed are garbage-collected after a grace period (see `REPO_GC_INTERVAL`). + +**LFS is automatic**, the same way it is for a git client: if the repo's `.gitattributes` marks a path as `filter=lfs` (including attributes added in the very same commit), the server stores the content as an LFS object and commits a pointer instead. Content that already _is_ a valid pointer passes through untouched, so pre-uploading big files via the LFS API (presigned, straight to the bucket) and committing the pointer yourself remains the efficient path for large objects. + +API commits dispatch the same signed [webhooks](#webhooks) as a `git push` — consumers can't tell them apart. + ### Health The control port also serves an unauthenticated `GET /healthz` readiness probe. It returns `200 {"status":"ok"}` when the database is reachable and `503 {"status":"unavailable"}` otherwise, and backs the container `HEALTHCHECK`. ## Webhooks -Register a webhook on a repository and `headlessgit` will `POST` to it after every successful push. +Register a webhook on a repository and `headlessgit` will `POST` to it after every ref change — a `git push` or a commit created through the [content API](#writing-without-a-clone) produce identical events. One delivery is sent **per changed ref** (a branch/tag create, update, or delete — not per file or commit). The JSON body: diff --git a/images/achive.png b/images/archive.png similarity index 100% rename from images/achive.png rename to images/archive.png diff --git a/images/commit.png b/images/commit.png new file mode 100644 index 0000000000000000000000000000000000000000..fed25334f3683cf02704bbf2aec87831d8dffb25 GIT binary patch literal 367358 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 z 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

v22G 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

KQF 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 # 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

RR7vxSoT3Co5Lk%_b6&lh3^5com}_g)(VVol3~ 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%0A3`4M{_*Y4_i#(EWJvN`&Fa`AI9 zE|+AC=U>(ylVMlTodyXS?u^zi%|BGMG~Xw20U=L^Yj(9v^ZQ9C6*_3|;SIH#h&rDT z9=3Q?z9(<*49BX#=fFaSmpFvMp*sC_yZv@$=A#SkRKE^A7Ykcjb{4!Oo7{hvC1BSN z|NE6HBYRpZIVsv7fE-2MBmQx^0k&T8i{jsu*oK~=o>dRTI&bgz)Ho4RD*ow`3UzR! zPV%exy*^7!))4pd^itz=Pt~~wG40{7PYEBkn74KeWnB>1X01CqBQ-cN<@w>{ya>9z zqb<;;_u1&G$XZLq%lK`p3pZMSF$atueB58i-0=Ku?KSgx{Gq4y{Ztd4Wi!4_E*UKkQDR2Tdp~%rom~U z{?9n~>mRAfP-?hUHEp@~dCKHU1pT(18Y>J89j6=6pl>h^HTvml!w+@d7gfULRUXK4 z5RE1Yr1_A*fxOY+7|u=i>g1FE#zgGMnKHn=s<*lvb5*Y&h zltN`B6w_MQ%mYUAYJIxiPo8)6Hh7tcJxYIj6Jt;ZIj6FzxOY1VmrN5O1i}&w)o%Er z0R5#~df+NJI-ymEal5_F%7}}6RY*#^) z;K>TEkN%w)2A#y>(w7#042k!F>syT)`EQC+Tq?$J7sXpBTc5Hv4bC1z4V`OiedM#Q zIU3k^&oUC}Gc&1COnL z!(FF|_jDTGr#{x1aJPQ-IgbGMbM#Vh2q6KktaUUGP{QG!t{oOGtg<*m-UswDwJD*Q zR{#ocJL*U+FKPP`4~eLLK=2;d&aS^I>5hpX&vfj{h^c_@kOjN6dp9G9bG8V#FCLPs zH=V5>$Km!gFQfFxlLIu-v%qQ~tZq)oZBtK*k_AVtzo(thkOgkUw&4qB(>-S{{&yxa zBic4&ug|zKIbnc~-yU$lhyl2LrFv(WH%q3rE4(CZ)A7T0HmV3lRu3>no&UB_N@&ex zblw3}oFNP)bMg+adn|tHM^Ldph~^?c?W&_V&IXuv`_I#SgUb0c_0%&{wWtm|1M(Dz zf`HgNArK6&h>9dqED@@b(1av_00Ue-wa}*1xAOR`GP;Z=#n*NGK@{&Ji;{^~v!+G? z9t(|rZI!XNJ(816;3-Ik7qn-QxfILG=;O<>z5aFeORI>>UewnG%_1+HKS||LkS*={&l0&XCeZ?T$_< zfOj+^Yob=@dAxcGU|LRAO|gdpAV`Zq{Ie+Y_h%LrDi-HT<-VVq81L7Wk<0P9Y8%@7C0Eimd2r_BbcSIUdvb=p z`Plv1U;6$Ezg{#(eV7=xE2IZE*GZ^w)Zgsy2f1TtBHBE!2-LRpjG&7s3vv-cqs}H^{rkdFs zn&j?VOjxxE2`#QI3oxms9a0|l>xsSp*`maOg}sA5tGiO_`Sj&bIq$-n@$;I)S>_94 z_YdNht0Wbiat=<}c9nlzD|Y>{s3RmK?QaWox>8sIgp}ZJd;V7a!!BNoudNv%5rcb- zwr-UA!L=ITwA+E)Fkm>pU4jku=1ZF?pHu-U$f5XjTKhumTi%qJ#mVPClZKyt13xDh zjqg`*YxvQ%)*6gk^vZV$jq!N(p8DN=&maROH2zmj53iQ``Y`BtY5M|Mg-oc)Y%J#- z4^(Ig%z6S^Wv8Pf$Jub9rx3V7iQOd{L7zPe2CN$NXV4VGK@rB(@5U6 z-qkhf}x?_vD%=$=d#?;GuiJ%WinRNI!0Gd7QIZ ztDh-fsEO;4hvegl)_|#q-X-Hs(0DdFxqI}#V*8}ugYc!!@NHYQyL_f^B70n)6{eQ#Wje9hSB29Xdbx*sQ9mK`Dn zO&;Q6Os*{TZNYijSbV5>(pF)I3yrW+Ipq+hFZ^kqzkl|=(xiMj&bv}`YBg-MdePfz zqC(kCv*PFdFHgLTr@z;zeS9@v^Y&fdqxteS9E)L_`l@uP{HIASB~wwE0MCAreBD>q zd#4q;!wy0}rq;$*HmU%6UKUafTEga>z;PQ9R&Wnbe?qRWh@#cr4IAHTfrXn3&@-T~ z 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 UhQc2-@IUL+RkhD&s#yN@e^AFJ{{R30 literal 0 HcmV?d00001