v0.34.0 7c1886f

release.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package ports
4
5import (
6	"bnema.dev/ermite/internal/domain"
7	"context"
8	"io"
9)
10
11// ReleaseWrite atomically changes one repository's metadata. Every write
12// requires UsageVersion (zero requires absence), and each record's Version.
13// Used includes both uploading and uploaded assets.
14type ReleaseWrite struct {
15	Repo                        domain.RepoName
16	SetLatest                   bool  // false leaves the latest index unchanged
17	LatestID                    int64 // zero means no eligible release when SetLatest
18	Used                        int64
19	UsageVersion                uint64
20	PutReleases, DeleteReleases []domain.Release
21	PutAssets, DeleteAssets     []domain.ReleaseAsset
22}
23
24// ReleaseStore keeps metadata, never contents. *kvstore.Releases implements it.
25type ReleaseStore interface {
26	GetLatestRelease(ctx context.Context, repo domain.RepoName) (domain.Release, error)
27	NextReleaseID(ctx context.Context) (int64, error)
28	ReleaseUsage(ctx context.Context, repo domain.RepoName) (used int64, version uint64, err error)
29	GetRelease(ctx context.Context, repo domain.RepoName, id int64) (domain.Release, error)
30	GetReleaseByTag(ctx context.Context, repo domain.RepoName, tag string) (domain.Release, error)
31	ReleaseRepo(ctx context.Context, id int64) (domain.RepoName, error)
32	ListReleases(ctx context.Context, repo domain.RepoName) ([]domain.Release, error)
33	GetAsset(ctx context.Context, id int64) (domain.ReleaseAsset, error)
34	GetAssetByName(ctx context.Context, repo domain.RepoName, releaseID int64, name string) (domain.ReleaseAsset, error)
35	ListAssets(ctx context.Context, repo domain.RepoName, releaseID int64) ([]domain.ReleaseAsset, error)
36	AllAssets(ctx context.Context) ([]domain.ReleaseAsset, error)
37	ApplyReleases(ctx context.Context, w ReleaseWrite) error
38}
39
40// ReleaseLimits defaults to domain.DefaultReleaseAssetMax (ERMITE_RELEASE_ASSET_MAX),
41// domain.DefaultReleaseAssetsMax (ERMITE_RELEASE_ASSETS_MAX), and
42// domain.DefaultReleaseQuota (ERMITE_RELEASE_QUOTA).
43type ReleaseLimits struct{ AssetMax, AssetsMax, Quota int64 }
44type CreateReleaseParams struct {
45	Tag, TargetCommitish, Title, Notes string
46	Draft, Prerelease, MakeLatest      bool
47}
48type UpdateReleaseParams struct {
49	Tag, TargetCommitish, Title, Notes *string
50	Draft, Prerelease, MakeLatest      *bool
51}
52
53// ReleaseRef selects exactly one of ID, Tag, Latest.
54type ReleaseRef struct {
55	ID     int64
56	Tag    string
57	Latest bool
58}
59
60// AssetRef selects ID, (Tag, Name), or (Latest, Name).
61type AssetRef struct {
62	ID        int64
63	Tag, Name string
64	Latest    bool
65}
66type UploadAssetParams struct {
67	ReleaseID                int64
68	Name, Label, ContentType string
69	Size                     int64
70	Replace                  bool
71}
72type UpdateAssetParams struct{ Name, Label *string }
73type ReleaseUsage struct {
74	Used   int64
75	Limits ReleaseLimits
76}
77type AssetChunk struct {
78	Asset *domain.ReleaseAsset
79	Data  []byte
80}
81type ReleasePage struct {
82	Releases      []domain.Release
83	NextPageToken string
84}
85
86// ReleaseService manages releases and streams assets; *usecase.Releases implements it.
87type ReleaseService interface {
88	CreateRelease(ctx context.Context, p domain.Principal, repo domain.RepoName, params CreateReleaseParams) (domain.Release, error)
89	GetRelease(ctx context.Context, p domain.Principal, repo domain.RepoName, ref ReleaseRef) (domain.Release, error)
90	ListReleases(ctx context.Context, p domain.Principal, repo domain.RepoName, pageSize int, pageToken string) (ReleasePage, error)
91	UpdateRelease(ctx context.Context, p domain.Principal, repo domain.RepoName, id int64, params UpdateReleaseParams) (domain.Release, error)
92	DeleteRelease(ctx context.Context, p domain.Principal, repo domain.RepoName, id int64) error
93	ListAssets(ctx context.Context, p domain.Principal, repo domain.RepoName, releaseID int64) ([]domain.ReleaseAsset, error)
94	UploadAsset(ctx context.Context, p domain.Principal, repo domain.RepoName, params UploadAssetParams, body io.Reader) (domain.ReleaseAsset, error)
95	UpdateAsset(ctx context.Context, p domain.Principal, repo domain.RepoName, assetID int64, params UpdateAssetParams) (domain.ReleaseAsset, error)
96	DeleteAsset(ctx context.Context, p domain.Principal, repo domain.RepoName, assetID int64) error
97	GetAsset(ctx context.Context, p domain.Principal, repo domain.RepoName, ref AssetRef) (domain.ReleaseAsset, error)
98	// DownloadAsset sends metadata first, then chunks at most domain.CIArtifactChunk;
99	// length less than zero reads to the end.
100	DownloadAsset(ctx context.Context, p domain.Principal, repo domain.RepoName, ref AssetRef, offset, length int64, send func(AssetChunk) error) error
101	Usage(ctx context.Context, p domain.Principal, repo domain.RepoName) (ReleaseUsage, error)
102}
103
104// ReleaseTagWriter creates lightweight tags without moving existing refs.
105// *gitcli.Git implements it. An existing ref returns domain.ErrAlreadyExists.
106type ReleaseTagWriter interface {
107	CreateTag(ctx context.Context, repo domain.RepoName, tag string, target domain.ObjectID) error
108}
109
110// ReleaseTagTrigger handles tag deletion; *usecase.Releases implements it.
111type ReleaseTagTrigger interface {
112	OnRefsMoved(ctx context.Context, repo domain.RepoName, updates []domain.RefUpdate)
113}
114
115// ReleaseSweeper removes stale assets and blobs; *usecase.Releases implements it.
116type ReleaseSweeper interface{ Sweep(ctx context.Context) }
117
118// ReleaseRepoCleaner removes contents after metadata deletion; *usecase.Releases implements it.
119type ReleaseRepoCleaner interface {
120	AssetsOf(ctx context.Context, repo domain.RepoName) ([]domain.ReleaseAsset, error)
121	OnRepoDeleted(ctx context.Context, repo domain.RepoName, assets []domain.ReleaseAsset)
122}

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 43

↑↓ moveenter openesc close