v0.29.0 55fcc8f

budget.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package domain
4
5import (
6	"fmt"
7	"math"
8)
9
10// ValidateCommitObjects checks a request before any repository I/O. max is the
11// caller's commit-count limit.
12func ValidateCommitObjects(ids []ObjectID, max int) error {
13	if len(ids) > max {
14		return fmt.Errorf("%w: %d commit objects asked, at most %d", ErrInvalid, len(ids), max)
15	}
16	for _, id := range ids {
17		if id.IsZero() {
18			return fmt.Errorf("%w: empty commit id", ErrInvalidObjectID)
19		}
20	}
21	return nil
22}
23
24// CommitObjectBudget bounds a batch of raw commits. Its zero value is ready to
25// use. Admission is a preview; Charge records only successfully read content.
26type CommitObjectBudget struct {
27	total int64
28	seen  map[ObjectID]bool
29}
30
31func (b *CommitObjectBudget) Seen(id ObjectID) bool { return b.seen[id] }
32
33func (b *CommitObjectBudget) Admit(id ObjectID, commit bool, size int64) (take, stop bool) {
34	if b.Seen(id) || !commit || size < 0 || size > MaxCommitObjectBytes {
35		return false, false
36	}
37	if size > MaxCommitObjectsBytes-b.total {
38		return false, true
39	}
40	return true, false
41}
42
43func (b *CommitObjectBudget) Charge(id ObjectID, size int64) {
44	if b.seen == nil {
45		b.seen = make(map[ObjectID]bool)
46	}
47	b.seen[id] = true
48	b.total += size
49}
50
51// DiffBudget owns file selection and retained hunk accounting. Omitted files
52// consume no budget; streaming readers may use a copy while attempting a file.
53type DiffBudget struct {
54	limits               DiffLimits
55	linesLeft, bytesLeft int
56	// fileBytes is bytesLeft when the current file started (StartFile).
57	fileBytes int
58}
59
60func NewDiffBudget(limits DiffLimits) DiffBudget {
61	return DiffBudget{limits: limits, linesLeft: limits.MaxTotalLines, bytesLeft: limits.MaxTotalBytes, fileBytes: limits.MaxTotalBytes}
62}
63
64func (b DiffBudget) Window(files int) (kept, from, to int, truncated bool) {
65	kept = files
66	if b.limits.MaxFiles > 0 && kept > b.limits.MaxFiles {
67		kept = b.limits.MaxFiles
68		truncated = true
69	}
70	from, to = max(b.limits.From, 0), kept
71	if b.limits.To > 0 {
72		to = min(b.limits.To, kept)
73	}
74	return
75}
76
77// Admit decides whether the hunks of a file are read. read is false with
78// OmitNone for a binary file or one without changed lines (nothing to show).
79// Otherwise read is false with the reason the file is omitted. path is the path
80// a comment designates (see FileDiff.CommentPath).
81func (b DiffBudget) Admit(binary bool, path string, changed int) (read bool, why FileOmission) {
82	switch {
83	case binary || changed <= 0:
84		return false, OmitNone
85	case b.limits.SkipGenerated && IsGeneratedPath(path):
86		return false, OmitGenerated
87	case b.limits.MaxAloneLines > 0 && changed > b.limits.MaxAloneLines:
88		return false, OmitUnavailable
89	case b.limits.MaxFileLines > 0 && changed > b.limits.MaxFileLines:
90		return false, OmitLarge
91	case b.limits.MaxTotalLines > 0 && changed > b.linesLeft, b.bytesLeft <= 0:
92		return false, OmitBudget
93	}
94	return true, OmitNone
95}
96
97// FileLines is the most changed lines the next file may have; math.MaxInt when
98// neither MaxFileLines nor MaxTotalLines limits it.
99func (b DiffBudget) FileLines() int {
100	n := math.MaxInt
101	if b.limits.MaxFileLines > 0 {
102		n = b.limits.MaxFileLines
103	}
104	if b.limits.MaxTotalLines > 0 {
105		n = min(n, b.linesLeft)
106	}
107	return n
108}
109
110// StartFile marks the start of a file's lines, for ChargeLine to tell a file
111// over the byte limit on its own from one that met the bytes of earlier files.
112func (b *DiffBudget) StartFile() { b.fileBytes = b.bytesLeft }
113
114// ChargeLine accounts for decoded text bytes and, for additions or deletions,
115// one changed line. Context consumes bytes only. It returns OmitNone when the
116// line fits and OmitBudget when the changed lines ran out. When the bytes run
117// out it returns OmitBudget if files read before this one (since StartFile)
118// spent some of them, as this file may still fit on its own, and
119// OmitUnavailable if this file alone is over MaxTotalBytes.
120func (b *DiffBudget) ChargeLine(bytes int, changed bool) FileOmission {
121	if changed && b.limits.MaxTotalLines > 0 {
122		b.linesLeft--
123	}
124	b.bytesLeft -= bytes
125	switch {
126	case b.limits.MaxTotalLines > 0 && b.linesLeft < 0:
127		return OmitBudget
128	case b.bytesLeft < 0 && b.fileBytes < b.limits.MaxTotalBytes:
129		return OmitBudget
130	case b.bytesLeft < 0:
131		return OmitUnavailable
132	}
133	return OmitNone
134}

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 44

↑↓ moveenter openesc close