Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 69b72d3

Browse files
committed
Add Stats() to Commit
Stats() is similar to `git show --stat <hash>`.
1 parent 0672868 commit 69b72d3

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

plumbing/object/commit.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,72 @@ func (b *Commit) Encode(o plumbing.EncodedObject) error {
265265
return err
266266
}
267267

268+
// FileStat stores the status of changes in content of a file.
269+
type FileStat struct {
270+
Name string
271+
Addition int
272+
Deletion int
273+
}
274+
275+
func (fs FileStat) String() string {
276+
totalChanges := fs.Addition + fs.Deletion
277+
adds := strings.Repeat("+", fs.Addition)
278+
dels := strings.Repeat("-", fs.Deletion)
279+
return fmt.Sprintf(" %s | %d %s%s", fs.Name, totalChanges, adds, dels)
280+
}
281+
282+
// FileStats is a collection of FileStat.
283+
type FileStats []FileStat
284+
285+
// Stats shows the status
286+
func (c *Commit) Stats() (FileStats, error) {
287+
var fileStats FileStats
288+
289+
// Get the previous commit.
290+
ci := c.Parents()
291+
parentCommit, err := ci.Next()
292+
if err != nil {
293+
return nil, err
294+
}
295+
296+
patch, err := parentCommit.Patch(c)
297+
if err != nil {
298+
return nil, err
299+
}
300+
301+
filePatches := patch.FilePatches()
302+
for _, fp := range filePatches {
303+
cs := FileStat{}
304+
from, to := fp.Files()
305+
if from == nil {
306+
// New File is created.
307+
cs.Name = to.Path()
308+
} else if to == nil {
309+
// File is deleted.
310+
cs.Name = from.Path()
311+
} else if from.Path() != to.Path() {
312+
// File is renamed.
313+
cs.Name = fmt.Sprintf("%s => %s", from.Path(), to.Path())
314+
} else {
315+
// File is modified.
316+
cs.Name = from.Path()
317+
}
318+
319+
for _, chunk := range fp.Chunks() {
320+
switch chunk.Type() {
321+
case 1:
322+
cs.Addition += strings.Count(chunk.Content(), "\n")
323+
case 2:
324+
cs.Deletion += strings.Count(chunk.Content(), "\n")
325+
}
326+
}
327+
328+
fileStats = append(fileStats, cs)
329+
}
330+
331+
return fileStats, nil
332+
}
333+
268334
func (c *Commit) String() string {
269335
return fmt.Sprintf(
270336
"%s %s\nAuthor: %s\nDate: %s\n\n%s\n",

plumbing/object/commit_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,27 @@ RUysgqjcpT8+iQM1PblGfHR4XAhuOqN5Fx06PSaFZhqvWFezJ28/CLyX5q+oIVk=
258258
c.Assert(err, IsNil)
259259
c.Assert(decoded.PGPSignature, Equals, pgpsignature)
260260
}
261+
262+
func (s *SuiteCommit) TestStat(c *C) {
263+
aCommit := s.commit(c, plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
264+
fileStats, err := aCommit.Stats()
265+
c.Assert(err, IsNil)
266+
267+
c.Assert(fileStats[0].Name, Equals, "vendor/foo.go")
268+
c.Assert(fileStats[0].Addition, Equals, 7)
269+
c.Assert(fileStats[0].Deletion, Equals, 0)
270+
c.Assert(fileStats[0].String(), Equals, " vendor/foo.go | 7 +++++++")
271+
272+
// Stats for another commit.
273+
aCommit = s.commit(c, plumbing.NewHash("918c48b83bd081e863dbe1b80f8998f058cd8294"))
274+
fileStats, err = aCommit.Stats()
275+
c.Assert(err, IsNil)
276+
277+
c.Assert(fileStats[0].Name, Equals, "go/example.go")
278+
c.Assert(fileStats[0].Addition, Equals, 142)
279+
c.Assert(fileStats[0].Deletion, Equals, 0)
280+
281+
c.Assert(fileStats[1].Name, Equals, "php/crappy.php")
282+
c.Assert(fileStats[1].Addition, Equals, 259)
283+
c.Assert(fileStats[1].Deletion, Equals, 0)
284+
}

0 commit comments

Comments
 (0)