-
Notifications
You must be signed in to change notification settings - Fork 127
/
commit.go
174 lines (143 loc) · 4.63 KB
/
commit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Copyright 2015 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package git
import (
"bytes"
"io"
"io/ioutil"
"net/http"
"strings"
"sync"
)
// Commit contains information of a Git commit.
type Commit struct {
// The SHA-1 hash of the commit.
ID *SHA1
// The author of the commit.
Author *Signature
// The committer of the commit.
Committer *Signature
// The full commit message.
Message string
parents []*SHA1
*Tree
submodules Submodules
submodulesOnce sync.Once
submodulesErr error
}
// Summary returns first line of commit message.
func (c *Commit) Summary() string {
return strings.Split(c.Message, "\n")[0]
}
// ParentsCount returns number of parents of the commit. It returns 0 if this is
// the root commit, otherwise returns 1, 2, etc.
func (c *Commit) ParentsCount() int {
return len(c.parents)
}
// ParentID returns the SHA-1 hash of the n-th parent (0-based) of this commit.
// It returns an ErrParentNotExist if no such parent exists.
func (c *Commit) ParentID(n int) (*SHA1, error) {
if n >= len(c.parents) {
return nil, ErrParentNotExist
}
return c.parents[n], nil
}
// Parent returns the n-th parent commit (0-based) of this commit. It returns
// ErrRevisionNotExist if no such parent exists.
func (c *Commit) Parent(n int, opts ...CatFileCommitOptions) (*Commit, error) {
id, err := c.ParentID(n)
if err != nil {
return nil, err
}
return c.repo.CatFileCommit(id.String(), opts...)
}
// CommitByPath returns the commit of the path in the state of this commit.
func (c *Commit) CommitByPath(opts ...CommitByRevisionOptions) (*Commit, error) {
return c.repo.CommitByRevision(c.ID.String(), opts...)
}
// CommitsByPage returns a paginated list of commits in the state of this
// commit. The returned list is in reverse chronological order.
func (c *Commit) CommitsByPage(page, size int, opts ...CommitsByPageOptions) ([]*Commit, error) {
return c.repo.CommitsByPage(c.ID.String(), page, size, opts...)
}
// SearchCommits searches commit message with given pattern. The returned list
// is in reverse chronological order.
func (c *Commit) SearchCommits(pattern string, opts ...SearchCommitsOptions) ([]*Commit, error) {
return c.repo.SearchCommits(c.ID.String(), pattern, opts...)
}
// ShowNameStatus returns name status of the commit.
func (c *Commit) ShowNameStatus(opts ...ShowNameStatusOptions) (*NameStatus, error) {
return c.repo.ShowNameStatus(c.ID.String(), opts...)
}
// CommitsCount returns number of total commits up to this commit.
func (c *Commit) CommitsCount(opts ...RevListCountOptions) (int64, error) {
return c.repo.RevListCount([]string{c.ID.String()}, opts...)
}
// FilesChangedAfter returns a list of files changed after given commit ID.
func (c *Commit) FilesChangedAfter(after string, opts ...DiffNameOnlyOptions) ([]string, error) {
return c.repo.DiffNameOnly(after, c.ID.String(), opts...)
}
// CommitsAfter returns a list of commits after given commit ID up to this
// commit. The returned list is in reverse chronological order.
func (c *Commit) CommitsAfter(after string, opts ...RevListOptions) ([]*Commit, error) {
return c.repo.RevList([]string{after + "..." + c.ID.String()}, opts...)
}
// Ancestors returns a list of ancestors of this commit in reverse chronological
// order.
func (c *Commit) Ancestors(opts ...LogOptions) ([]*Commit, error) {
if c.ParentsCount() == 0 {
return []*Commit{}, nil
}
var opt LogOptions
if len(opts) > 0 {
opt = opts[0]
}
opt.Skip++
return c.repo.Log(c.ID.String(), opt)
}
type limitWriter struct {
W io.Writer
N int64
}
func (w *limitWriter) Write(p []byte) (int, error) {
if w.N <= 0 {
return len(p), nil
}
limit := int64(len(p))
if limit > w.N {
limit = w.N
}
n, err := w.W.Write(p[:limit])
w.N -= int64(n)
// Prevent "short write" error
return len(p), err
}
func (c *Commit) isImageFile(blob *Blob, err error) (bool, error) {
if err != nil {
if err == ErrNotBlob {
return false, nil
}
return false, err
}
buf := new(bytes.Buffer)
buf.Grow(512)
stdout := &limitWriter{
W: buf,
N: int64(buf.Cap()),
}
err = blob.Pipeline(stdout, ioutil.Discard)
if err != nil {
return false, err
}
return strings.Contains(http.DetectContentType(buf.Bytes()), "image/"), nil
}
// IsImageFile returns true if the blob of the commit is an image by subpath.
func (c *Commit) IsImageFile(subpath string) (bool, error) {
return c.isImageFile(c.Blob(subpath))
}
// IsImageFileByIndex returns true if the blob of the commit is an image by
// index.
func (c *Commit) IsImageFileByIndex(index string) (bool, error) {
return c.isImageFile(c.BlobByIndex(index))
}