From 69b72d30b125b07f69f2b1f53c44b273d7cb4da9 Mon Sep 17 00:00:00 2001 From: Sunny Date: Fri, 6 Oct 2017 17:17:29 +0530 Subject: Add Stats() to Commit Stats() is similar to `git show --stat `. --- plumbing/object/commit.go | 66 ++++++++++++++++++++++++++++++++++++++++++ plumbing/object/commit_test.go | 24 +++++++++++++++ 2 files changed, 90 insertions(+) (limited to 'plumbing/object') diff --git a/plumbing/object/commit.go b/plumbing/object/commit.go index 66ecabd..e5faa38 100644 --- a/plumbing/object/commit.go +++ b/plumbing/object/commit.go @@ -265,6 +265,72 @@ func (b *Commit) Encode(o plumbing.EncodedObject) error { return err } +// FileStat stores the status of changes in content of a file. +type FileStat struct { + Name string + Addition int + Deletion int +} + +func (fs FileStat) String() string { + totalChanges := fs.Addition + fs.Deletion + adds := strings.Repeat("+", fs.Addition) + dels := strings.Repeat("-", fs.Deletion) + return fmt.Sprintf(" %s | %d %s%s", fs.Name, totalChanges, adds, dels) +} + +// FileStats is a collection of FileStat. +type FileStats []FileStat + +// Stats shows the status +func (c *Commit) Stats() (FileStats, error) { + var fileStats FileStats + + // Get the previous commit. + ci := c.Parents() + parentCommit, err := ci.Next() + if err != nil { + return nil, err + } + + patch, err := parentCommit.Patch(c) + if err != nil { + return nil, err + } + + filePatches := patch.FilePatches() + for _, fp := range filePatches { + cs := FileStat{} + from, to := fp.Files() + if from == nil { + // New File is created. + cs.Name = to.Path() + } else if to == nil { + // File is deleted. + cs.Name = from.Path() + } else if from.Path() != to.Path() { + // File is renamed. + cs.Name = fmt.Sprintf("%s => %s", from.Path(), to.Path()) + } else { + // File is modified. + cs.Name = from.Path() + } + + for _, chunk := range fp.Chunks() { + switch chunk.Type() { + case 1: + cs.Addition += strings.Count(chunk.Content(), "\n") + case 2: + cs.Deletion += strings.Count(chunk.Content(), "\n") + } + } + + fileStats = append(fileStats, cs) + } + + return fileStats, nil +} + func (c *Commit) String() string { return fmt.Sprintf( "%s %s\nAuthor: %s\nDate: %s\n\n%s\n", diff --git a/plumbing/object/commit_test.go b/plumbing/object/commit_test.go index 2d04e77..f17f1c6 100644 --- a/plumbing/object/commit_test.go +++ b/plumbing/object/commit_test.go @@ -258,3 +258,27 @@ RUysgqjcpT8+iQM1PblGfHR4XAhuOqN5Fx06PSaFZhqvWFezJ28/CLyX5q+oIVk= c.Assert(err, IsNil) c.Assert(decoded.PGPSignature, Equals, pgpsignature) } + +func (s *SuiteCommit) TestStat(c *C) { + aCommit := s.commit(c, plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5")) + fileStats, err := aCommit.Stats() + c.Assert(err, IsNil) + + c.Assert(fileStats[0].Name, Equals, "vendor/foo.go") + c.Assert(fileStats[0].Addition, Equals, 7) + c.Assert(fileStats[0].Deletion, Equals, 0) + c.Assert(fileStats[0].String(), Equals, " vendor/foo.go | 7 +++++++") + + // Stats for another commit. + aCommit = s.commit(c, plumbing.NewHash("918c48b83bd081e863dbe1b80f8998f058cd8294")) + fileStats, err = aCommit.Stats() + c.Assert(err, IsNil) + + c.Assert(fileStats[0].Name, Equals, "go/example.go") + c.Assert(fileStats[0].Addition, Equals, 142) + c.Assert(fileStats[0].Deletion, Equals, 0) + + c.Assert(fileStats[1].Name, Equals, "php/crappy.php") + c.Assert(fileStats[1].Addition, Equals, 259) + c.Assert(fileStats[1].Deletion, Equals, 0) +} -- cgit