main 81ede3b

git.proto RawHistoryFolder

1// SPDX-License-Identifier: MIT
2
3syntax = "proto3";
4
5package ermite;
6
7import "ermite/types.proto";
8
9// RefKind is the kind of a Git ref.
10enum RefKind {
11  // Not set. In ListRefsRequest.kinds it is rejected; never returned.
12  REF_KIND_UNSPECIFIED = 0;
13  // A branch (refs/heads/*).
14  REF_KIND_BRANCH = 1;
15  // A tag (refs/tags/*), lightweight or annotated.
16  REF_KIND_TAG = 2;
17  // The symbolic ref HEAD, that is the default branch.
18  REF_KIND_HEAD = 3;
19}
20
21// EntryKind is the kind of an entry of a Git tree.
22enum EntryKind {
23  // Not set. Never returned.
24  ENTRY_KIND_UNSPECIFIED = 0;
25  // A regular, non-executable file (mode 100644).
26  ENTRY_KIND_FILE = 1;
27  // An executable file (mode 100755).
28  ENTRY_KIND_EXECUTABLE = 2;
29  // A directory (mode 040000).
30  ENTRY_KIND_DIRECTORY = 3;
31  // A symbolic link (mode 120000). The blob content is the link target.
32  ENTRY_KIND_SYMLINK = 4;
33  // A submodule commit (mode 160000). The id is a commit of another
34  // repository, which this one does not contain.
35  ENTRY_KIND_SUBMODULE = 5;
36}
37
38// FileStatus tells what a commit did to a file.
39enum FileStatus {
40  // Not set. Never returned.
41  FILE_STATUS_UNSPECIFIED = 0;
42  // The file was added.
43  FILE_STATUS_ADDED = 1;
44  // The file was deleted.
45  FILE_STATUS_DELETED = 2;
46  // The content or the mode of the file changed.
47  FILE_STATUS_MODIFIED = 3;
48  // The file was moved, possibly with changes. Rename detection is done by Git.
49  FILE_STATUS_RENAMED = 4;
50  // The file was copied from another file, possibly with changes.
51  FILE_STATUS_COPIED = 5;
52  // The type of the entry changed, for example a file became a symbolic link.
53  FILE_STATUS_TYPE_CHANGED = 6;
54}
55
56// FileOmission tells why a changed file has no hunks although it changed.
57enum FileOmission {
58  // The file is not omitted: its hunks are present, or it has none to show
59  // (binary, pure rename, mode change), or it is outside the requested window.
60  FILE_OMISSION_UNSPECIFIED = 0;
61  // The file is generated or vendored, by its path: its hunks were not read.
62  // It can be read on its own.
63  FILE_OMISSION_GENERATED = 1;
64  // The file changes more lines than the per-file limit. It can be read on its own.
65  FILE_OMISSION_LARGE = 2;
66  // The file did not fit in what remained of the total limits of the diff.
67  // It can be read on its own.
68  FILE_OMISSION_BUDGET = 3;
69  // The file's text exceeds the memory limit of a diff: it cannot be shown,
70  // even on its own. Clone the repository to read it.
71  FILE_OMISSION_UNAVAILABLE = 4;
72}
73
74// LineKind tells how a line of a hunk relates to the two sides of a diff.
75enum LineKind {
76  // Not set. Never returned.
77  LINE_KIND_UNSPECIFIED = 0;
78  // The line is present, unchanged, on both sides.
79  LINE_KIND_CONTEXT = 1;
80  // The line exists only on the new side.
81  LINE_KIND_ADDITION = 2;
82  // The line exists only on the old side.
83  LINE_KIND_DELETION = 3;
84}
85
86// GitService reads the Git data of repositories. It is read-only: pushes go
87// through Git itself.
88//
89// Every RPC takes the repository name. A repository that does not exist or
90// that the caller cannot read gives not_found. A revision is a branch name, a
91// tag name or a commit id (full, or an unambiguous abbreviation of at least 7
92// characters); empty means HEAD. A revision or path that does not exist gives
93// not_found; so does an empty repository, which has no commit to resolve.
94service GitService {
95  // ListRefs lists the branches, tags and HEAD of a repository. Refs are
96  // ordered by kind (HEAD, branches, tags) then by name.
97  rpc ListRefs(ListRefsRequest) returns (ListRefsResponse);
98  // GetTree lists the entries of a directory at a revision. Fails with
99  // not_found if the path does not exist and invalid_argument if it is not a
100  // directory.
101  rpc GetTree(GetTreeRequest) returns (GetTreeResponse);
102  // ListPaths lists the paths of every file and symbolic link of a revision,
103  // recursively, in Git tree order (the order of `git ls-tree -r`). Directories
104  // and submodules are not listed, nor paths GetBlob cannot address (not valid
105  // UTF-8, or with a control character). Fails with not_found for an unknown
106  // revision or an empty repository. Servers that have it advertise the
107  // feature "git.list_paths" in GetVersion.
108  rpc ListPaths(ListPathsRequest) returns (ListPathsResponse);
109  // GetBlob streams the content of a file at a revision, in chunks of at most
110  // 64 KiB. The first message carries the metadata in info, then the chunks
111  // follow; the memory used by the server does not depend on the file size.
112  // Fails with not_found if the path does not exist and invalid_argument if it
113  // is not a file.
114  rpc GetBlob(GetBlobRequest) returns (stream GetBlobResponse);
115  // ListCommits lists the history reachable from a revision, newest first
116  // (Git's default order), optionally limited to the commits that touched a
117  // path. A page_token that points deeper than 100,000 commits into the
118  // history is invalid_argument.
119  rpc ListCommits(ListCommitsRequest) returns (ListCommitsResponse);
120  // GetCommit returns one commit with its statistics and its diff.
121  rpc GetCommit(GetCommitRequest) returns (GetCommitResponse);
122  // ResolveRevision turns a revision into the id of the commit it designates.
123  rpc ResolveRevision(ResolveRevisionRequest) returns (ResolveRevisionResponse);
124}
125
126// Ref is a branch, a tag or HEAD.
127message Ref {
128  // Name is the full ref name, for example "refs/heads/main" or
129  // "refs/tags/v1.0.0". For HEAD it is "HEAD".
130  string name = 1;
131  // ShortName is the name without its "refs/heads/" or "refs/tags/" prefix. For
132  // HEAD it is the short name of the default branch, or empty if HEAD points
133  // to a branch that does not exist yet.
134  string short_name = 2;
135  // Kind is the kind of the ref.
136  RefKind kind = 3;
137  // Id is the id of the object the ref points to. For an annotated tag it is
138  // the id of the tag object.
139  string id = 4;
140  // CommitId is the id of the commit the ref designates once annotated tags are
141  // followed. It equals id for branches and lightweight tags. It is empty for
142  // a tag that points to something other than a commit.
143  string commit_id = 5;
144}
145
146// ListRefsRequest selects the refs to list.
147message ListRefsRequest {
148  // Repo is the repository name.
149  string repo = 1;
150  // Kinds restricts the result to these kinds. Empty means all kinds.
151  repeated RefKind kinds = 2;
152  // PageSize is the maximum number of refs to return. 0 means the server
153  // default; values above the server maximum are lowered to it.
154  int32 page_size = 3;
155  // PageToken is the next_page_token of a previous response. Empty for the
156  // first page.
157  string page_token = 4;
158}
159
160// ListRefsResponse is one page of refs.
161message ListRefsResponse {
162  // Refs are the refs of this page.
163  repeated Ref refs = 1;
164  // NextPageToken is passed as page_token to get the next page. Empty when
165  // there is no next page.
166  string next_page_token = 2;
167}
168
169// TreeEntry is one entry of a directory.
170message TreeEntry {
171  // Name is the name of the entry in its directory, without slash.
172  string name = 1;
173  // Path is the path of the entry from the repository root, with "/"
174  // separators and no leading slash.
175  string path = 2;
176  // Kind is the kind of the entry.
177  EntryKind kind = 3;
178  // Mode is the Git file mode, for example 0o100644 (33188 in decimal).
179  uint32 mode = 4;
180  // Id is the object id of the blob, tree or submodule commit.
181  string id = 5;
182  // Size is the size in bytes of a file or symbolic link. It is 0 for
183  // directories and submodules.
184  int64 size = 6;
185  // LastCommit is the latest commit that changed the entry. Set only when the
186  // request asked for it with include_last_commit.
187  Commit last_commit = 7;
188}
189
190// GetTreeRequest selects a directory.
191message GetTreeRequest {
192  // Repo is the repository name.
193  string repo = 1;
194  // Revision is a branch, a tag or a commit id. Empty means HEAD.
195  string revision = 2;
196  // Path is the directory, from the repository root, with "/" separators.
197  // Empty means the root.
198  string path = 3;
199  // IncludeLastCommit asks for the last commit of every entry in last_commit.
200  // It costs one history walk, so it is off by default and the server may be
201  // slow on large directories.
202  bool include_last_commit = 4;
203}
204
205// GetTreeResponse lists a directory.
206message GetTreeResponse {
207  // CommitId is the id of the commit the revision resolved to.
208  string commit_id = 1;
209  // TreeId is the object id of the listed directory.
210  string tree_id = 2;
211  // Entries are the entries of the directory: directories first, then the other
212  // entries, each group ordered by name. A response holds at most 5,000
213  // entries (a server limit that may change; rely on truncated, not on the
214  // number): past that, the first 5,000 in this order are returned and
215  // truncated is set. Paging may be added later, additively.
216  repeated TreeEntry entries = 3;
217  // LastCommitsTruncated is true when include_last_commit was set and the
218  // server gave a last_commit to the first entries only (at most 200 of them,
219  // in the order of entries), because each one costs a history lookup. The
220  // other entries have no last_commit although they have one in Git.
221  bool last_commits_truncated = 4;
222  // Truncated is true when the directory has more entries than the response
223  // holds; entries are then the first ones in the documented order.
224  bool truncated = 5;
225}
226
227// ListPathsRequest selects a revision.
228message ListPathsRequest {
229  // Repo is the repository name.
230  string repo = 1;
231  // Revision is a branch, a tag or a commit id. Empty means HEAD.
232  string revision = 2;
233}
234
235// ListPathsResponse lists the file paths of a revision.
236message ListPathsResponse {
237  // CommitId is the id of the commit the revision resolved to.
238  string commit_id = 1;
239  // TreeId is the object id of its root tree.
240  string tree_id = 2;
241  // Paths are the paths of the files and symbolic links, in Git tree order. A
242  // response holds at most 100,000 paths and 8 MiB of path bytes (server limits
243  // that may change; rely on truncated, not on the numbers).
244  repeated string paths = 3;
245  // Truncated is true when more paths exist past the first ones returned.
246  bool truncated = 4;
247}
248
249// BlobInfo describes a file.
250message BlobInfo {
251  // Id is the object id of the blob.
252  string id = 1;
253  // Path is the path of the file from the repository root.
254  string path = 2;
255  // Size is the size of the whole content in bytes.
256  int64 size = 3;
257  // Binary is true if the content is binary, with Git's rule: a NUL byte in the
258  // first 8,000 bytes.
259  bool binary = 4;
260  // MediaType is the detected media type, for example "text/plain" or
261  // "image/png", from the file name and the first bytes. It is
262  // "application/octet-stream" when unknown.
263  string media_type = 5;
264  // Mode is the Git file mode, for example 0o100644 (33188 in decimal).
265  uint32 mode = 6;
266}
267
268// GetBlobRequest selects a file.
269message GetBlobRequest {
270  // Repo is the repository name.
271  string repo = 1;
272  // Revision is a branch, a tag or a commit id. Empty means HEAD.
273  string revision = 2;
274  // Path is the file, from the repository root. It is required.
275  string path = 3;
276}
277
278// GetBlobResponse is one message of the content stream.
279message GetBlobResponse {
280  // Info describes the file. Set in the first message of the stream only.
281  BlobInfo info = 1;
282  // Chunk is the next part of the content, at most 64 KiB, in order. The first
283  // message may have an empty chunk. The chunks of a stream add up to
284  // info.size bytes.
285  bytes chunk = 2;
286}
287
288// ListCommitsRequest selects a page of history.
289message ListCommitsRequest {
290  // Repo is the repository name.
291  string repo = 1;
292  // Revision is where the history starts: a branch, a tag or a commit id.
293  // Empty means HEAD.
294  string revision = 2;
295  // Path restricts the result to the commits that changed this file or
296  // directory. Empty means the whole history.
297  string path = 3;
298  // PageSize is the maximum number of commits to return. 0 means the server
299  // default; values above 100 are lowered to 100.
300  int32 page_size = 4;
301  // PageToken is the next_page_token of a previous response, to continue the
302  // same listing. Empty for the first page. Other fields must be unchanged.
303  string page_token = 5;
304}
305
306// ListCommitsResponse is one page of commits.
307message ListCommitsResponse {
308  // Commits are the commits of this page, newest first.
309  repeated Commit commits = 1;
310  // NextPageToken is passed as page_token to get the next page. Empty when
311  // there is no next page.
312  string next_page_token = 2;
313}
314
315// GetCommitRequest selects a commit.
316message GetCommitRequest {
317  // Repo is the repository name.
318  string repo = 1;
319  // Revision is a branch, a tag or a commit id. Empty means HEAD.
320  string revision = 2;
321}
322
323// GetCommitResponse holds a commit, its statistics and its diff.
324message GetCommitResponse {
325  // Commit is the commit metadata.
326  Commit commit = 1;
327  // Stats are the totals over all the changed files, including files that the
328  // diff omits or truncates.
329  DiffStats stats = 2;
330  // Diff is the structured diff against the first parent, or against the empty
331  // tree for a root commit. For a merge commit this is the change relative to
332  // the first parent.
333  Diff diff = 3;
334}
335
336// DiffStats are the totals of a diff.
337message DiffStats {
338  // FilesChanged is the number of changed files.
339  int32 files_changed = 1;
340  // Additions is the number of added lines. Binary files count for 0.
341  int32 additions = 2;
342  // Deletions is the number of deleted lines. Binary files count for 0.
343  int32 deletions = 3;
344}
345
346// Diff is the structured difference introduced by a commit.
347//
348// The server limits its size: at most 300 files, at most 2,000 lines in one
349// file and at most 20,000 lines in total (hunk lines, context included). These
350// numbers are server behaviour and may change; clients must rely on the
351// truncated flags, not on the numbers.
352message Diff {
353  // Files are the changed files, ordered by path. Files past the file limit are
354  // omitted.
355  repeated FileDiff files = 1;
356  // Truncated is true when the diff is incomplete: files were omitted past the
357  // file limit, or at least one listed file has omitted set. DiffStats still count everything.
358  bool truncated = 2;
359}
360
361// FileDiff is the change of one file.
362message FileDiff {
363  // OldPath is the path before the commit. Empty for an added file.
364  string old_path = 1;
365  // NewPath is the path after the commit. Empty for a deleted file.
366  string new_path = 2;
367  // Status tells what happened to the file.
368  FileStatus status = 3;
369  // OldMode is the Git file mode before the commit, or 0 for an added file.
370  uint32 old_mode = 4;
371  // NewMode is the Git file mode after the commit, or 0 for a deleted file.
372  uint32 new_mode = 5;
373  // OldId is the blob id before the commit. Empty for an added file.
374  string old_id = 6;
375  // NewId is the blob id after the commit. Empty for a deleted file.
376  string new_id = 7;
377  // Binary is true if Git treats the file as binary (numstat reports "-"). A
378  // binary file has no hunks and additions and deletions are 0.
379  bool binary = 8;
380  // Additions is the number of added lines.
381  int32 additions = 9;
382  // Deletions is the number of deleted lines.
383  int32 deletions = 10;
384  // Similarity is the percentage (0-100) of unchanged content for a renamed or
385  // copied file, and 0 otherwise.
386  int32 similarity = 11;
387  // Truncated is true when the file exceeded a diff limit: hunks is then empty
388  // although the file changed. Additions and deletions remain accurate. It is
389  // kept for compatibility and equals omitted != FILE_OMISSION_UNSPECIFIED.
390  bool truncated = 12;
391  // Hunks are the changed regions, in file order. Empty for a binary file, a
392  // truncated file, a pure rename and a mode-only change.
393  repeated Hunk hunks = 13;
394  // Omitted tells why hunks is empty although the file changed. truncated is
395  // true exactly when omitted is not FILE_OMISSION_UNSPECIFIED.
396  FileOmission omitted = 14;
397}
398
399// Hunk is a contiguous changed region with its context.
400message Hunk {
401  // OldStart is the 1-based first line of the region in the old file. 0 when
402  // old_lines is 0 and the file was added.
403  int32 old_start = 1;
404  // OldLines is the number of old-side lines in the hunk.
405  int32 old_lines = 2;
406  // NewStart is the 1-based first line of the region in the new file. 0 when
407  // new_lines is 0 and the file was deleted.
408  int32 new_start = 3;
409  // NewLines is the number of new-side lines in the hunk.
410  int32 new_lines = 4;
411  // Header is the text after the second "@@" of the hunk header, usually the
412  // enclosing function. It may be empty.
413  string header = 5;
414  // Lines are the lines of the hunk, in order.
415  repeated Line lines = 6;
416}
417
418// Line is one line of a hunk.
419message Line {
420  // Kind tells which side the line belongs to.
421  LineKind kind = 1;
422  // OldNumber is the 1-based line number on the old side. 0 for an addition.
423  int32 old_number = 2;
424  // NewNumber is the 1-based line number on the new side. 0 for a deletion.
425  int32 new_number = 3;
426  // Text is the content without the line terminator. Bytes that are not valid
427  // UTF-8 are replaced by the replacement character.
428  string text = 4;
429  // NoNewlineAtEof is true when this is the last line of its side and the file
430  // does not end with a line break there.
431  bool no_newline_at_eof = 5;
432}
433
434// ResolveRevisionRequest names a revision.
435message ResolveRevisionRequest {
436  // Repo is the repository name.
437  string repo = 1;
438  // Revision is a branch, a tag or a commit id. Empty means HEAD.
439  string revision = 2;
440}
441
442// ResolveRevisionResponse holds the resolved commit.
443message ResolveRevisionResponse {
444  // CommitId is the full id of the commit the revision designates, after
445  // following annotated tags.
446  string commit_id = 1;
447  // Ref is the full name of the ref the revision matched, for example
448  // "refs/heads/main". Empty when the revision was a commit id or for HEAD
449  // when it is resolved by default.
450  string ref = 2;
451}

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 18

↑↓ moveenter openesc close