browse.go

  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}