5
5
package git
6
6
7
7
import (
8
+ "bufio"
9
+ "container/list"
8
10
"fmt"
11
+ "net/http"
9
12
"strconv"
10
13
"strings"
11
14
@@ -20,8 +23,18 @@ type Commit struct {
20
23
Committer * Signature
21
24
CommitMessage string
22
25
23
- parents []sha1 // SHA1 strings
24
- // submodules map[string]*SubModule
26
+ parents []sha1 // SHA1 strings
27
+ submodules map [string ]* SubModule
28
+ }
29
+
30
+ // Message returns the commit message. Same as retrieving CommitMessage directly.
31
+ func (c * Commit ) Message () string {
32
+ return c .CommitMessage
33
+ }
34
+
35
+ // Summary returns first line of commit message.
36
+ func (c * Commit ) Summary () string {
37
+ return strings .Split (c .CommitMessage , "\n " )[0 ]
25
38
}
26
39
27
40
// ParentID returns oid of n-th parent (0-based index).
@@ -47,14 +60,41 @@ func (c *Commit) Parent(n int) (*Commit, error) {
47
60
}
48
61
49
62
// ParentCount returns number of parents of the commit.
50
- // 0 if this is the root commit, otherwise 1,2, etc.
63
+ // 0 if this is the root commit, otherwise 1,2, etc.
51
64
func (c * Commit ) ParentCount () int {
52
65
return len (c .parents )
53
66
}
54
67
55
- // GetCommitOfRelPath return the commit of relative path object.
56
- func (c * Commit ) GetCommitOfRelPath (relpath string ) (* Commit , error ) {
57
- return c .repo .getCommitOfRelPath (c .ID , relpath )
68
+ func isImageFile (data []byte ) (string , bool ) {
69
+ contentType := http .DetectContentType (data )
70
+ if strings .Index (contentType , "image/" ) != - 1 {
71
+ return contentType , true
72
+ }
73
+ return contentType , false
74
+ }
75
+
76
+ func (c * Commit ) IsImageFile (name string ) bool {
77
+ blob , err := c .GetBlobByPath (name )
78
+ if err != nil {
79
+ return false
80
+ }
81
+
82
+ dataRc , err := blob .Data ()
83
+ if err != nil {
84
+ return false
85
+ }
86
+ buf := make ([]byte , 1024 )
87
+ n , _ := dataRc .Read (buf )
88
+ if n > 0 {
89
+ buf = buf [:n ]
90
+ }
91
+ _ , isImage := isImageFile (buf )
92
+ return isImage
93
+ }
94
+
95
+ // GetCommitByPath return the commit of relative path object.
96
+ func (c * Commit ) GetCommitByPath (relpath string ) (* Commit , error ) {
97
+ return c .repo .getCommitByPathWithID (c .ID , relpath )
58
98
}
59
99
60
100
// AddAllChanges marks local changes to be ready for commit.
@@ -82,19 +122,102 @@ func CommitChanges(repoPath, message string, author *Signature) error {
82
122
return err
83
123
}
84
124
85
- // CommitsCount returns number of total commits of until given revision.
86
- func CommitsCount (repoPath , revision string ) (int64 , error ) {
125
+ func commitsCount (repoPath , revision , relpath string ) (int64 , error ) {
126
+ var cmd * Command
127
+ isFallback := false
87
128
if version .Compare (gitVersion , "1.8.0" , "<" ) {
88
- stdout , err := NewCommand ("log" , "--pretty=format:''" , revision ).RunInDir (repoPath )
89
- if err != nil {
90
- return 0 , err
91
- }
92
- return int64 (len (strings .Split (stdout , "\n " ))), nil
129
+ isFallback = true
130
+ cmd = NewCommand ("log" , "--pretty=format:''" )
131
+ } else {
132
+ cmd = NewCommand ("rev-list" , "--count" )
133
+ }
134
+ cmd .AddArguments (revision )
135
+ if len (relpath ) > 0 {
136
+ cmd .AddArguments ("--" , relpath )
93
137
}
94
138
95
- stdout , err := NewCommand ( "rev-list" , "--count" , revision ) .RunInDir (repoPath )
139
+ stdout , err := cmd .RunInDir (repoPath )
96
140
if err != nil {
97
141
return 0 , err
98
142
}
143
+
144
+ if isFallback {
145
+ return int64 (len (strings .Split (stdout , "\n " ))), nil
146
+ }
99
147
return strconv .ParseInt (strings .TrimSpace (stdout ), 10 , 64 )
100
148
}
149
+
150
+ // CommitsCount returns number of total commits of until given revision.
151
+ func CommitsCount (repoPath , revision string ) (int64 , error ) {
152
+ return commitsCount (repoPath , revision , "" )
153
+ }
154
+
155
+ func (c * Commit ) CommitsCount () (int64 , error ) {
156
+ return CommitsCount (c .repo .Path , c .ID .String ())
157
+ }
158
+
159
+ func (c * Commit ) CommitsByRange (page int ) (* list.List , error ) {
160
+ return c .repo .commitsByRange (c .ID , page )
161
+ }
162
+
163
+ func (c * Commit ) CommitsBefore () (* list.List , error ) {
164
+ return c .repo .getCommitsBefore (c .ID )
165
+ }
166
+
167
+ func (c * Commit ) CommitsBeforeUntil (commitID string ) (* list.List , error ) {
168
+ endCommit , err := c .repo .GetCommit (commitID )
169
+ if err != nil {
170
+ return nil , err
171
+ }
172
+ return c .repo .CommitsBetween (c , endCommit )
173
+ }
174
+
175
+ func (c * Commit ) SearchCommits (keyword string ) (* list.List , error ) {
176
+ return c .repo .searchCommits (c .ID , keyword )
177
+ }
178
+
179
+ func (c * Commit ) GetSubModule (entryname string ) (* SubModule , error ) {
180
+ modules , err := c .GetSubModules ()
181
+ if err != nil {
182
+ return nil , err
183
+ }
184
+ return modules [entryname ], nil
185
+ }
186
+
187
+ func (c * Commit ) GetSubModules () (map [string ]* SubModule , error ) {
188
+ if c .submodules != nil {
189
+ return c .submodules , nil
190
+ }
191
+
192
+ entry , err := c .GetTreeEntryByPath (".gitmodules" )
193
+ if err != nil {
194
+ return nil , err
195
+ }
196
+ rd , err := entry .Blob ().Data ()
197
+ if err != nil {
198
+ return nil , err
199
+ }
200
+
201
+ scanner := bufio .NewScanner (rd )
202
+ c .submodules = make (map [string ]* SubModule )
203
+ var ismodule bool
204
+ var path string
205
+ for scanner .Scan () {
206
+ if strings .HasPrefix (scanner .Text (), "[submodule" ) {
207
+ ismodule = true
208
+ continue
209
+ }
210
+ if ismodule {
211
+ fields := strings .Split (scanner .Text (), "=" )
212
+ k := strings .TrimSpace (fields [0 ])
213
+ if k == "path" {
214
+ path = strings .TrimSpace (fields [1 ])
215
+ } else if k == "url" {
216
+ c .submodules [path ] = & SubModule {path , strings .TrimSpace (fields [1 ])}
217
+ ismodule = false
218
+ }
219
+ }
220
+ }
221
+
222
+ return c .submodules , nil
223
+ }
0 commit comments