1package repository
2
3import (
4 "bytes"
5 "fmt"
6 "io"
7 "strconv"
8 "time"
9)
10
11// ChangeStatus describes how a file was affected by a commit.
12type ChangeStatus string
13
14const (
15 ChangeStatusAdded ChangeStatus = "added"
16 ChangeStatusModified ChangeStatus = "modified"
17 ChangeStatusDeleted ChangeStatus = "deleted"
18 ChangeStatusRenamed ChangeStatus = "renamed"
19)
20
21func (s ChangeStatus) MarshalGQL(w io.Writer) {
22 switch s {
23 case ChangeStatusAdded:
24 fmt.Fprint(w, strconv.Quote("ADDED"))
25 case ChangeStatusModified:
26 fmt.Fprint(w, strconv.Quote("MODIFIED"))
27 case ChangeStatusDeleted:
28 fmt.Fprint(w, strconv.Quote("DELETED"))
29 case ChangeStatusRenamed:
30 fmt.Fprint(w, strconv.Quote("RENAMED"))
31 default:
32 panic(fmt.Sprintf("unknown ChangeStatus value %q", string(s)))
33 }
34}
35
36func (s *ChangeStatus) UnmarshalGQL(v any) error {
37 str, ok := v.(string)
38 if !ok {
39 return fmt.Errorf("enums must be strings")
40 }
41 switch str {
42 case "ADDED":
43 *s = ChangeStatusAdded
44 case "MODIFIED":
45 *s = ChangeStatusModified
46 case "DELETED":
47 *s = ChangeStatusDeleted
48 case "RENAMED":
49 *s = ChangeStatusRenamed
50 default:
51 return fmt.Errorf("%q is not a valid ChangeStatus", str)
52 }
53 return nil
54}
55
56// DiffLineType is the role of a line within a unified diff hunk.
57type DiffLineType string
58
59const (
60 DiffLineContext DiffLineType = "context"
61 DiffLineAdded DiffLineType = "added"
62 DiffLineDeleted DiffLineType = "deleted"
63)
64
65func (t DiffLineType) MarshalGQL(w io.Writer) {
66 switch t {
67 case DiffLineContext:
68 fmt.Fprint(w, strconv.Quote("CONTEXT"))
69 case DiffLineAdded:
70 fmt.Fprint(w, strconv.Quote("ADDED"))
71 case DiffLineDeleted:
72 fmt.Fprint(w, strconv.Quote("DELETED"))
73 default:
74 panic(fmt.Sprintf("unknown DiffLineType value %q", string(t)))
75 }
76}
77
78func (t *DiffLineType) UnmarshalGQL(v any) error {
79 str, ok := v.(string)
80 if !ok {
81 return fmt.Errorf("enums must be strings")
82 }
83 switch str {
84 case "CONTEXT":
85 *t = DiffLineContext
86 case "ADDED":
87 *t = DiffLineAdded
88 case "DELETED":
89 *t = DiffLineDeleted
90 default:
91 return fmt.Errorf("%q is not a valid DiffLineType", str)
92 }
93 return nil
94}
95
96// GitRefType is the kind of git reference: a branch, a tag, or a detached commit.
97type GitRefType string
98
99const (
100 // GitRefTypeBranch refers to a local branch (refs/heads/*).
101 GitRefTypeBranch GitRefType = "BRANCH"
102 // GitRefTypeTag refers to an annotated or lightweight tag (refs/tags/*).
103 GitRefTypeTag GitRefType = "TAG"
104 // GitRefTypeCommit represents a detached HEAD pointing directly at a commit.
105 GitRefTypeCommit GitRefType = "COMMIT"
106)
107
108func (e GitRefType) IsValid() bool {
109 switch e {
110 case GitRefTypeBranch, GitRefTypeTag, GitRefTypeCommit:
111 return true
112 }
113 return false
114}
115
116func (e GitRefType) String() string { return string(e) }
117
118func (e *GitRefType) UnmarshalGQL(v any) error {
119 str, ok := v.(string)
120 if !ok {
121 return fmt.Errorf("enums must be strings")
122 }
123 *e = GitRefType(str)
124 if !e.IsValid() {
125 return fmt.Errorf("%s is not a valid GitRefType", str)
126 }
127 return nil
128}
129
130func (e GitRefType) MarshalGQL(w io.Writer) {
131 fmt.Fprint(w, strconv.Quote(e.String()))
132}
133
134func (e *GitRefType) UnmarshalJSON(b []byte) error {
135 s, err := strconv.Unquote(string(b))
136 if err != nil {
137 return err
138 }
139 return e.UnmarshalGQL(s)
140}
141
142func (e GitRefType) MarshalJSON() ([]byte, error) {
143 var buf bytes.Buffer
144 e.MarshalGQL(&buf)
145 return buf.Bytes(), nil
146}
147
148type RefMeta struct {
149 // Full reference name, e.g. refs/heads/main or refs/tags/v1.0.
150 Name string `json:"name"`
151 // Short name, e.g. main or v1.0.
152 ShortName string `json:"shortName"`
153 // Whether this reference is a branch or a tag.
154 Type GitRefType `json:"type"`
155 // Commit hash the reference points to.
156 Hash string `json:"hash"`
157}
158
159// CommitMeta holds the metadata for a single commit, suitable for listing.
160type CommitMeta struct {
161 Hash Hash
162 Message string
163 AuthorName string
164 AuthorEmail string
165 Date time.Time
166 Parents []Hash
167}
168
169// ChangedFile describes a file that was modified in a commit.
170type ChangedFile struct {
171 Path string
172 OldPath *string // non-nil for renames
173 Status ChangeStatus
174}
175
176// CommitDetail extends CommitMeta with the full message and the list of
177// changed files (relative to the first parent).
178type CommitDetail struct {
179 CommitMeta
180 FullMessage string
181 Files []ChangedFile
182}
183
184// DiffLine represents one line in a unified diff hunk.
185type DiffLine struct {
186 Type DiffLineType
187 Content string
188 OldLine int
189 NewLine int
190}
191
192// DiffHunk is a contiguous block of changes in a unified diff.
193type DiffHunk struct {
194 OldStart int
195 OldLines int
196 NewStart int
197 NewLines int
198 Lines []DiffLine
199}
200
201// FileDiff is the diff for a single file in a commit.
202type FileDiff struct {
203 Path string
204 OldPath *string // non-nil for renames
205 IsBinary bool
206 IsNew bool
207 IsDelete bool
208 Hunks []DiffHunk
209}
210
211// BranchInfo describes a local branch returned by RepoBrowse.Branches.
212type BranchInfo struct {
213 Name string
214 Hash Hash // commit hash
215}
216
217// TagInfo describes a tag returned by RepoBrowse.Tags.
218type TagInfo struct {
219 Name string
220 // Hash is always the target commit hash. For annotated tags the tag
221 // object is dereferenced; for lightweight tags this is the ref hash.
222 Hash Hash
223}