v0.29.0 55fcc8f

commitobjects.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package gitcli
4
5import (
6	"context"
7	"fmt"
8
9	"bnema.dev/ermite/internal/domain"
10	"bnema.dev/ermite/internal/ports"
11)
12
13var _ ports.CommitObjectReader = (*Git)(nil)
14
15// ReadCommitObjects reads the raw content of commits with the cat-file pool:
16// one `info` per id, then `contents` for the commits of acceptable size. Ids
17// that are missing, are not commits, or are larger than
18// domain.MaxCommitObjectBytes are left out. The read ends at the first commit
19// that would take the total over domain.MaxCommitObjectsBytes (known from
20// `info`, before any content is read, so the stream stays consistent).
21//
22//hexcheck:ignore suspicious-business-logic-in-adapter streams object headers and bytes; eligibility, deduplication and byte limits are decided by domain.CommitObjectBudget, request validation by domain.ValidateCommitObjects
23func (g *Git) ReadCommitObjects(ctx context.Context, repo domain.RepoName, ids []domain.ObjectID) (map[domain.ObjectID][]byte, error) {
24	if err := domain.ValidateCommitObjects(ids, ports.MaxCommitLimit); err != nil {
25		return nil, err
26	}
27	dir, err := g.repoDir(repo)
28	if err != nil {
29		return nil, err
30	}
31	out := make(map[domain.ObjectID][]byte, len(ids))
32	err = g.cat.do(ctx, dir, func(c *catConn) error {
33		clear(out) // a retry on a fresh process starts over
34		var budget domain.CommitObjectBudget
35		for _, id := range ids {
36			if err := ctx.Err(); err != nil {
37				return err
38			}
39			if budget.Seen(id) {
40				continue
41			}
42			h, err := c.info(id.String())
43			if notFound(err) {
44				continue
45			}
46			if err != nil {
47				return err
48			}
49			take, stop := budget.Admit(id, h.Type == "commit", h.Size)
50			if stop {
51				break
52			}
53			if !take {
54				continue
55			}
56			_, data, err := c.contents(id.String(), domain.MaxCommitObjectBytes)
57			if err != nil {
58				return err
59			}
60			out[id] = data
61			budget.Charge(id, int64(len(data)))
62		}
63		return nil
64	})
65	if err != nil {
66		return nil, fmt.Errorf("read commit objects of %q: %w", repo, err)
67	}
68	return out, nil
69}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 3

Tags 44

↑↓ moveenter openesc close