55package git
66
77import (
8+ "bufio"
9+ "container/list"
810 "fmt"
11+ "net/http"
912 "strconv"
1013 "strings"
1114
@@ -20,8 +23,18 @@ type Commit struct {
2023 Committer * Signature
2124 CommitMessage string
2225
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 ]
2538}
2639
2740// ParentID returns oid of n-th parent (0-based index).
@@ -47,14 +60,41 @@ func (c *Commit) Parent(n int) (*Commit, error) {
4760}
4861
4962// 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.
5164func (c * Commit ) ParentCount () int {
5265 return len (c .parents )
5366}
5467
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 )
5898}
5999
60100// AddAllChanges marks local changes to be ready for commit.
@@ -82,19 +122,102 @@ func CommitChanges(repoPath, message string, author *Signature) error {
82122 return err
83123}
84124
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
87128 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 )
93137 }
94138
95- stdout , err := NewCommand ( "rev-list" , "--count" , revision ) .RunInDir (repoPath )
139+ stdout , err := cmd .RunInDir (repoPath )
96140 if err != nil {
97141 return 0 , err
98142 }
143+
144+ if isFallback {
145+ return int64 (len (strings .Split (stdout , "\n " ))), nil
146+ }
99147 return strconv .ParseInt (strings .TrimSpace (stdout ), 10 , 64 )
100148}
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