v0.27.0 0039612

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 applies the limits of the port and of the domain
23func (g *Git) ReadCommitObjects(ctx context.Context, repo domain.RepoName, ids []domain.ObjectID) (map[domain.ObjectID][]byte, error) {
24	if len(ids) > ports.MaxCommitLimit {
25		return nil, fmt.Errorf("%w: %d commit objects asked, at most %d", domain.ErrInvalid, len(ids), ports.MaxCommitLimit)
26	}
27	for _, id := range ids {
28		if id.IsZero() {
29			return nil, fmt.Errorf("%w: empty commit id", domain.ErrInvalidObjectID)
30		}
31	}
32	dir, err := g.repoDir(repo)
33	if err != nil {
34		return nil, err
35	}
36	out := make(map[domain.ObjectID][]byte, len(ids))
37	err = g.cat.do(ctx, dir, func(c *catConn) error {
38		clear(out) // a retry on a fresh process starts over
39		var total int64
40		for _, id := range ids {
41			if err := ctx.Err(); err != nil {
42				return err
43			}
44			if _, done := out[id]; done {
45				continue
46			}
47			h, err := c.info(id.String())
48			if notFound(err) {
49				continue
50			}
51			if err != nil {
52				return err
53			}
54			if h.Type != "commit" || h.Size > domain.MaxCommitObjectBytes {
55				continue
56			}
57			if total+h.Size > domain.MaxCommitObjectsBytes {
58				break
59			}
60			_, data, err := c.contents(id.String(), domain.MaxCommitObjectBytes)
61			if err != nil {
62				return err
63			}
64			out[id] = data
65			total += int64(len(data))
66		}
67		return nil
68	})
69	if err != nil {
70		return nil, fmt.Errorf("read commit objects of %q: %w", repo, err)
71	}
72	return out, nil
73}

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 2

Tags 45

↑↓ moveenter openesc close