detached 5278df2

dto.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package ports
4
5import (
6	"time"
7
8	"bnema.dev/ermite/internal/domain"
9)
10
11// The parameters and results of the use case interfaces (services.go). They
12// live here so that the adapters that call the use cases and the use cases
13// themselves share them without importing each other.
14
15// RepoPage is a page of repositories ordered by name.
16type RepoPage struct {
17	Repos []domain.Repo
18	// NextPageToken is empty on the last page.
19	NextPageToken string
20}
21
22// RepoView is a repository with the Git state that belongs in its summary.
23type RepoView struct {
24	domain.Repo // includes ActiveAt, the latest repository activity
25	// DefaultBranch is the branch HEAD points to, even when it does not exist
26	// yet; empty when HEAD is detached or the directory is missing.
27	DefaultBranch string
28}
29
30// CreateRepoParams are the settings of a new repository.
31type CreateRepoParams struct {
32	Name        domain.RepoName
33	Description string
34	// Topics are normalized by Create (see domain.NormalizeTopics).
35	Topics []string
36	// Visibility defaults to private when empty.
37	Visibility domain.Visibility
38}
39
40// UpdateRepoParams are the changes of Update; a nil field is left alone.
41type UpdateRepoParams struct {
42	Description *string
43	// Topics replaces the topics; an empty list clears them.
44	Topics        *[]string
45	Visibility    *domain.Visibility
46	DefaultBranch *string
47	// AllowedMergeModes replaces the allowed merge modes; it must hold at
48	// least one known mode.
49	AllowedMergeModes *[]domain.MergeMode
50	// FailingChecksBlock replaces the setting of that name.
51	FailingChecksBlock *bool
52	// Issues replaces the issues mode.
53	Issues *domain.IssuesMode
54}
55
56// TokenPage is a page of stored tokens, newest first.
57type TokenPage struct {
58	Tokens []domain.Token
59	// NextPageToken is empty on the last page.
60	NextPageToken string
61}
62
63// CreateTokenParams are the settings of a new token.
64type CreateTokenParams struct {
65	Label string
66	// Scopes must not be empty.
67	Scopes []domain.Scope
68	// Repos limits the token to these repositories; empty means every one.
69	Repos []domain.RepoName
70	// BranchPrefixes limits the token to the branches under these prefixes
71	// (see domain.ParseBranchPrefix); empty means every branch.
72	BranchPrefixes []string
73	// ExpiresAt is the zero time for a token that never expires.
74	ExpiresAt time.Time
75}
76
77// CreatedToken is a new token with its secret, which is shown once and never
78// stored.
79type CreatedToken struct {
80	Token  domain.Token
81	Secret string
82}
83
84// ListRefsParams selects the refs to list.
85type ListRefsParams struct {
86	// Kinds restricts the result; empty means every kind.
87	Kinds []domain.RefKind
88	// PageSize is 0 for the default, and lowered to MaxRefPageSize.
89	PageSize int
90	// PageToken is the NextPageToken of the previous page, or empty.
91	PageToken string
92}
93
94// RefPage is a page of refs.
95type RefPage struct {
96	Refs []domain.Ref
97	// NextPageToken is empty on the last page.
98	NextPageToken string
99}
100
101// ListCommitsParams selects a page of history.
102type ListCommitsParams struct {
103	// Revision is where the history starts; the zero value is HEAD. Ignored
104	// when PageToken is set: the token pins the commit the first page started
105	// from, so every page walks the same history even if a branch moves.
106	Revision domain.Revision
107	// Path limits the history to the commits that changed it. It must be the
108	// same on every page of a listing.
109	Path domain.TreePath
110	// PageSize is 0 for the default, and lowered to MaxPageSize.
111	PageSize int
112	// PageToken is the NextPageToken of the previous page, or empty.
113	PageToken string
114}
115
116// HistoryPage is a page of history, newest first.
117type HistoryPage struct {
118	Commits []domain.Commit
119	// NextPageToken is empty on the last page.
120	NextPageToken string
121}
122
123// RepoStats are the figures of a repository the home page shows.
124type RepoStats struct {
125	// Commits is the number of commits of the default branch; Recent of them
126	// were committed in the last RecentDays days.
127	Commits, Recent int
128	// LatestTag is the most recently created tag; nil without tags.
129	LatestTag *domain.TagInfo
130	// Activity is the number of commits of each of the last ActivityDays
131	// days, oldest first; the last day ends now. A day is 24 hours.
132	Activity []int
133	// Partial tells that the recent commits were more than MaxCommitTimes:
134	// Recent and Activity count only some of them.
135	Partial bool
136}
137
138// RecentDays is the window of RepoStats.Recent.
139const RecentDays = 30
140
141// ActivityDays is the span of RepoStats.Activity.
142const ActivityDays = 90
143
144// WatchParams select the events of a watch.
145type WatchParams struct {
146	// Topics are TopicHome or "repo:<name>"; empty means TopicHome.
147	Topics []string
148	// ResumeAfter is the id of the last event the caller saw; empty to
149	// receive only new events.
150	ResumeAfter string
151	// Client identifies where the watch comes from, for the limit per client
152	// (MaxWatchersPerClient): an opaque key such as a normalized address; the
153	// web passes its visitor's. Empty only for callers with no client, which
154	// count against MaxWatchers alone.
155	Client string
156	// Ready, when not nil, is called once the topics are valid and the watch
157	// is registered: events published from then on are not missed. Nothing is
158	// sent before it returns.
159	Ready func()
160}
161
162// WatchEvent is one item of a watch.
163type WatchEvent struct {
164	// ID identifies the event, for resuming. Empty on a gap.
165	ID string
166	// Gap tells that events were lost: the caller must reload what it shows.
167	// Event is nil then.
168	Gap bool
169	// Event is a domain.RepoCreated, RepoUpdated, RepoDeleted, PushEvent,
170	// MergeRequestOpened, MergeRequestMerged, MergeRequestClosed,
171	// MergeRequestReady, CommentAdded, RunUpdated or JobUpdated.
172	Event domain.Event
173	// Repo is the state of the repository at delivery, for RepoCreated and
174	// RepoUpdated.
175	Repo *RepoView
176}
177
178// CreateMergeRequestParams describes the merge request to open.
179type CreateMergeRequestParams struct {
180	Title       string
181	Description string
182	// Source is required; Target defaults to the default branch.
183	Source, Target string
184}
185
186// ListMergeRequestsParams selects a page of merge requests.
187type ListMergeRequestsParams struct {
188	// State restricts the result; empty means every state.
189	State domain.MRState
190	// PageSize is 0 for the default, and lowered to MaxPageSize.
191	PageSize int
192	// PageToken is the NextPageToken of the previous page, or empty.
193	PageToken string
194}
195
196// MergeRequestPage is a page of merge requests, highest number first.
197type MergeRequestPage struct {
198	MergeRequests []domain.MergeRequest
199	// NextPageToken is empty on the last page.
200	NextPageToken string
201	// Mergeability holds, by number, the mergeability of the open requests of
202	// the page (nil when the server does not compute it).
203	Mergeability map[int64]domain.Mergeability
204}
205
206// ListIssuesParams selects a page of issues from an IssueStore.
207type ListIssuesParams struct {
208	// State restricts the result; empty means every state.
209	State domain.IssueState
210	// PageSize is the most issues returned; 0 or less means no limit. The
211	// use case chooses it.
212	PageSize int
213	// PageToken is the NextPageToken of the previous page, or empty.
214	PageToken string
215}
216
217// IssuePage is a page of issues, highest number first.
218type IssuePage struct {
219	Issues []domain.Issue
220	// NextPageToken is empty on the last page.
221	NextPageToken string
222}
223
224// ListPendingParams selects a page of pending issues.
225type ListPendingParams struct {
226	// PageSize is the page size; the use case applies the default and the
227	// maximum, a store takes it as is (0: every one).
228	PageSize int
229	// PageToken is the NextPageToken of the previous page.
230	PageToken string
231}
232
233// PendingIssuePage is a page of pending issues, oldest first.
234type PendingIssuePage struct {
235	Issues        []domain.PendingIssue
236	NextPageToken string
237}
238
239// CreateIssueParams describes the issue to open.
240type CreateIssueParams struct {
241	Title string
242	Body  string
243}
244
245// IssueDetail is an issue with its comments.
246type IssueDetail struct {
247	Issue domain.Issue
248	// Comments are oldest first.
249	Comments []domain.IssueComment
250}
251
252// CompareResult describes source commits absent from target, newest first.
253type CompareResult struct {
254	Ahead  []domain.Commit
255	Behind bool
256	Exact  bool
257}
258
259// PushSummary counts a bounded range; More means additional commits exist.
260type PushSummary struct {
261	Count     int
262	More      bool
263	Rewritten bool
264}
265
266// MergeRequestDetail is a merge request with its review data.
267type MergeRequestDetail struct {
268	MergeRequest domain.MergeRequest
269	// NewCommits is the unread prefix of Commits; zero if the read head is absent.
270	NewCommits int
271	// HeadUnread reports whether the nonzero head differs from the shared read position.
272	HeadUnread bool
273	// Commits are the commits of the head that the target lacks, newest
274	// first, at most MaxMergeRequestCommits.
275	Commits          []domain.Commit
276	CommitsTruncated bool
277	// DiffBaseID is the commit the diff compares from; zero when the source
278	// branch is gone, then the diff is empty.
279	DiffBaseID domain.ObjectID
280	Stats      domain.DiffStats
281	Diff       domain.Diff
282	// Comments are the comments, oldest first.
283	Comments []domain.Comment
284	// Verdicts are the latest verdict per author in note ID order.
285	Verdicts []domain.AuthorVerdict
286	// Mergeability is zero unless the request is open.
287	Mergeability domain.Mergeability
288	// LastReadID is the head recorded by MarkRead; zero when none.
289	LastReadID domain.ObjectID
290	// LastReadLost tells that since-last-read was asked for, a head was
291	// recorded, but that commit is gone: the diff is against the target.
292	LastReadLost bool
293}
294
295// GetMergeRequestOptions say which diff MergeRequestService.Get reads.
296type GetMergeRequestOptions struct {
297	// SinceLastRead compares the head recorded by MarkRead with the head (see Get).
298	SinceLastRead bool
299	// Files, when set, lists every changed file, without the file-count
300	// limit, and reads the hunks of the files in the window only, each within
301	// the per-file and the total limits of domain.DefaultDiffLimits; generated
302	// files are listed collapsed (domain.OmitGenerated). With Full, the single
303	// file is read without the line limits. Unset, the diff is bounded by
304	// domain.DefaultDiffLimits and generated files are read (the API contract).
305	Files *FileWindow
306	// Base and Head, when not zero, are the diff the caller shows: Get
307	// returns domain.ErrConflict when the request's diff base or head differ
308	// (the branch moved, a read was marked).
309	Base, Head domain.ObjectID
310	// DiffOnly skips the commits of the request (Commits stays empty).
311	DiffOnly bool
312	// Load, when set with Files, is the index of a collapsed file Get reads in
313	// full and splices into the diff in place of its collapsed entry (the page
314	// of a client without scripts). Ignored when the index is out of range,
315	// the file is not collapsed, or there is no diff.
316	Load *int
317}
318
319// FileWindow is the range [From, To) of files whose hunks are read.
320//
321// Full asks for the one file From read in full: no line limit applies, only
322// the byte guard (domain.OneFileDiffLimits). It requires To == From+1; a
323// window with Full and any other To is domain.ErrInvalid.
324type FileWindow struct {
325	From, To int
326	Full     bool
327}
328
329// GetCommitOptions say which diff BrowseService.GetCommit reads.
330type GetCommitOptions struct {
331	// Files, when set, reads the hunks of a window of the files, as
332	// GetMergeRequestOptions.Files does. Unset (the zero value), the diff is
333	// bounded by domain.DefaultDiffLimits.
334	Files *FileWindow
335	// Page, without Files, reads the diff for a page: every file listed, the
336	// hunks of the first domain.CommitPageFiles files read, generated files
337	// collapsed, and the files past the window collapsed too
338	// (domain.OmitBudget). Combined with Files it is domain.ErrInvalid.
339	Page bool
340	// Load is the index of a collapsed file read in full and spliced into the
341	// diff, as GetMergeRequestOptions.Load. It requires Page.
342	Load *int
343}
344
345// AddCommentParams describes the comment to add.
346type AddCommentParams struct {
347	// ReplyTo names a non-deleted root; replies cannot specify an anchor or verdict.
348	ReplyTo int64
349	// StartLine starts an inclusive range, requiring a path and 1 <= StartLine < Line.
350	StartLine int
351	// Verdict requires mr:review and is only permitted on roots.
352	Verdict domain.Verdict
353	// Path, Line and Side designate a line of the diff; all empty for a
354	// general comment.
355	Path string
356	Line int
357	Side domain.DiffSide
358	Text string
359}
360
361// MergeParams describes the merge to perform.
362type MergeParams struct {
363	// Mode defaults to fast-forward.
364	Mode domain.MergeMode
365	// HeadID is the commit the caller reviewed; the source branch must still
366	// point to it.
367	HeadID domain.ObjectID
368	// DeleteSource deletes the source branch after the merge.
369	DeleteSource bool
370}
371
372// MergeResult is a merged request and what happened to its source branch.
373type MergeResult struct {
374	domain.MergeRequest
375	// SourceDeleted is true when DeleteSource was asked: the deletion is
376	// requested, and done asynchronously after the merge returned (it is
377	// skipped if the branch moved meanwhile).
378	SourceDeleted bool
379}
380
381// LoginLink is a login link as the owner receives it.
382type LoginLink struct {
383	// URL holds the secret: show it once, never log it.
384	URL       string
385	ExpiresAt time.Time
386}
387
388// InboxCounts are the numbers of open items across every repository, whatever
389// the filter.
390type InboxCounts struct{ MergeRequests, Issues, Pending int }
391
392// InboxOverview is what the owner has to look at across every repository: the
393// open merge requests and the open issues, most recently updated first. A
394// section for the items awaiting moderation can be added next to them.
395type InboxOverview struct {
396	Counts InboxCounts
397	// MergeRequests and Issues are those of the filtered repository, or of
398	// every repository when there is no filter. Counts always counts all.
399	MergeRequests []domain.MergeRequest
400	Issues        []domain.Issue
401	// Pending are the issues awaiting moderation, in every repository
402	// whatever the filter, oldest first. At most domain.MaxPendingIssues.
403	Pending []domain.PendingIssue
404	// Repos are the repositories that have at least one open item, by name,
405	// whatever the filter: they feed the filter itself.
406	Repos []domain.RepoName
407}
408
409// History query limits.
410const (
411	// MaxMergeRequestCommits bounds the commits returned with a merge request.
412	MaxMergeRequestCommits = 100
413	// MaxCompareCommits bounds a repository comparison.
414	MaxCompareCommits = 500
415	// MaxPushSummaryCommits bounds the commits counted in a push summary.
416	MaxPushSummaryCommits = 100
417)

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