Merge pull request #9 from mcuadros/blame-cleanup

blame code reorganization, and mutting the test
diff --git a/blame/blame.go b/blame.go
similarity index 82%
rename from blame/blame.go
rename to blame.go
index 7256a7b..66224fe 100644
--- a/blame/blame.go
+++ b/blame.go
@@ -6,7 +6,7 @@
 //
 // This package also provides a pretty print function to output the
 // results of a blame in a similar format to the git-blame command.
-package blame
+package git
 
 import (
 	"bytes"
@@ -16,14 +16,18 @@
 	"strings"
 	"unicode/utf8"
 
-	"gopkg.in/src-d/go-git.v2"
 	"gopkg.in/src-d/go-git.v2/core"
 	"gopkg.in/src-d/go-git.v2/diff"
-	"gopkg.in/src-d/go-git.v2/revlist"
 )
 
-// Blame returns the last commit that modified each line of a file in
-// a repository.
+type Blame struct {
+	Path  string
+	Rev   core.Hash
+	Lines []*line
+}
+
+// Blame returns the last commit that modified each line of a file in a
+// repository.
 //
 // The file to blame is identified by the input arguments: repo, commit and path.
 // The output is a slice of commits, one for each line in the file.
@@ -66,19 +70,9 @@
 //    1. Add memoization between revlist and assign.
 //
 //    2. It is using much more memory than needed, see the TODOs below.
-
-type Blame struct {
-	Repo  string
-	Path  string
-	Rev   string
-	Lines []*line
-}
-
-func New(repo *git.Repository, path string, commit *git.Commit) (*Blame, error) {
-	// init the internal blame struct
+func (c *Commit) Blame(path string) (*Blame, error) {
 	b := new(blame)
-	b.repo = repo
-	b.fRev = commit
+	b.fRev = c
 	b.path = path
 
 	// get all the file revisions
@@ -104,9 +98,8 @@
 	}
 
 	return &Blame{
-		Repo:  repo.URL,
 		Path:  path,
-		Rev:   commit.Hash.String(),
+		Rev:   c.Hash,
 		Lines: lines,
 	}, nil
 }
@@ -123,7 +116,7 @@
 	}
 }
 
-func newLines(contents []string, commits []*git.Commit) ([]*line, error) {
+func newLines(contents []string, commits []*Commit) ([]*line, error) {
 	if len(contents) != len(commits) {
 		return nil, errors.New("contents and commits have different length")
 	}
@@ -138,18 +131,18 @@
 // this struct is internally used by the blame function to hold its
 // inputs, outputs and state.
 type blame struct {
-	repo  *git.Repository // the repo holding the history of the file to blame
-	path  string          // the path of the file to blame
-	fRev  *git.Commit     // the commit of the final revision of the file to blame
-	revs  revlist.Revs    // the chain of revisions affecting the the file to blame
-	data  []string        // the contents of the file across all its revisions
-	graph [][]*git.Commit // the graph of the lines in the file across all the revisions TODO: not all commits are needed, only the current rev and the prev
+	path  string      // the path of the file to blame
+	fRev  *Commit     // the commit of the final revision of the file to blame
+	revs  []*Commit   // the chain of revisions affecting the the file to blame
+	data  []string    // the contents of the file across all its revisions
+	graph [][]*Commit // the graph of the lines in the file across all the revisions TODO: not all commits are needed, only the current rev and the prev
 }
 
 // calculte the history of a file "path", starting from commit "from", sorted by commit date.
 func (b *blame) fillRevs() error {
 	var err error
-	b.revs, err = revlist.NewRevs(b.repo, b.fRev, b.path)
+
+	b.revs, err = b.fRev.References(b.path)
 	if err != nil {
 		return err
 	}
@@ -158,7 +151,7 @@
 
 // build graph of a file from its revision history
 func (b *blame) fillGraphAndData() error {
-	b.graph = make([][]*git.Commit, len(b.revs))
+	b.graph = make([][]*Commit, len(b.revs))
 	b.data = make([]string, len(b.revs)) // file contents in all the revisions
 	// for every revision of the file, starting with the first
 	// one...
@@ -169,15 +162,15 @@
 			return nil
 		}
 		b.data[i] = file.Contents()
-		nLines := git.CountLines(b.data[i])
+		nLines := countLines(b.data[i])
 		// create a node for each line
-		b.graph[i] = make([]*git.Commit, nLines)
+		b.graph[i] = make([]*Commit, nLines)
 		// assign a commit to each node
 		// if this is the first revision, then the node is assigned to
 		// this first commit.
 		if i == 0 {
 			for j := 0; j < nLines; j++ {
-				b.graph[i][j] = (*git.Commit)(b.revs[i])
+				b.graph[i][j] = (*Commit)(b.revs[i])
 			}
 		} else {
 			// if this is not the first commit, then assign to the old
@@ -191,11 +184,11 @@
 
 // sliceGraph returns a slice of commits (one per line) for a particular
 // revision of a file (0=first revision).
-func (b *blame) sliceGraph(i int) []*git.Commit {
+func (b *blame) sliceGraph(i int) []*Commit {
 	fVs := b.graph[i]
-	result := make([]*git.Commit, 0, len(fVs))
+	result := make([]*Commit, 0, len(fVs))
 	for _, v := range fVs {
-		c := git.Commit(*v)
+		c := Commit(*v)
 		result = append(result, &c)
 	}
 	return result
@@ -209,7 +202,7 @@
 	sl := -1 // source line
 	dl := -1 // destination line
 	for h := range hunks {
-		hLines := git.CountLines(hunks[h].Text)
+		hLines := countLines(hunks[h].Text)
 		for hl := 0; hl < hLines; hl++ {
 			switch {
 			case hunks[h].Type == 0:
@@ -218,7 +211,7 @@
 				b.graph[c][dl] = b.graph[p][sl]
 			case hunks[h].Type == 1:
 				dl++
-				b.graph[c][dl] = (*git.Commit)(b.revs[c])
+				b.graph[c][dl] = (*Commit)(b.revs[c])
 			case hunks[h].Type == -1:
 				sl++
 			default:
@@ -255,7 +248,7 @@
 }
 
 // utility function to pretty print the author.
-func prettyPrintAuthor(c *git.Commit) string {
+func prettyPrintAuthor(c *Commit) string {
 	return fmt.Sprintf("%s %s", c.Author.Name, c.Author.When.Format("2006-01-02"))
 }
 
diff --git a/blame/blame_test.go b/blame_test.go
similarity index 95%
rename from blame/blame_test.go
rename to blame_test.go
index 3c24852..622d2af 100644
--- a/blame/blame_test.go
+++ b/blame_test.go
@@ -1,38 +1,25 @@
-package blame
+package git
 
 import (
-	"bytes"
 	"os"
-	"testing"
 
-	"gopkg.in/src-d/go-git.v2"
 	"gopkg.in/src-d/go-git.v2/core"
 	"gopkg.in/src-d/go-git.v2/formats/packfile"
 
 	. "gopkg.in/check.v1"
 )
 
-func Test(t *testing.T) { TestingT(t) }
-
-type SuiteCommon struct {
-	repos map[string]*git.Repository
+type BlameCommon struct {
+	repos map[string]*Repository
 }
 
-var _ = Suite(&SuiteCommon{})
-
-var fixtureRepos = [...]struct {
-	url      string
-	packfile string
-}{
-	{"https://github.com/tyba/git-fixture.git", "../formats/packfile/fixtures/git-fixture.ofs-delta"},
-	{"https://github.com/spinnaker/spinnaker.git", "../formats/packfile/fixtures/spinnaker-spinnaker.pack"},
-}
+var _ = Suite(&BlameCommon{})
 
 // create the repositories of the fixtures
-func (s *SuiteCommon) SetUpSuite(c *C) {
-	s.repos = make(map[string]*git.Repository, 0)
+func (s *BlameCommon) SetUpSuite(c *C) {
+	s.repos = make(map[string]*Repository, 0)
 	for _, fixRepo := range fixtureRepos {
-		repo := git.NewPlainRepository()
+		repo := NewPlainRepository()
 		repo.URL = fixRepo.url
 
 		d, err := os.Open(fixRepo.packfile)
@@ -60,7 +47,7 @@
 	blames []string // the commits blamed for each line
 }
 
-func (s *SuiteCommon) mockBlame(t blameTest, c *C) (blame *Blame) {
+func (s *BlameCommon) mockBlame(t blameTest, c *C) (blame *Blame) {
 	repo, ok := s.repos[t.repo]
 	c.Assert(ok, Equals, true)
 
@@ -85,16 +72,15 @@
 	}
 
 	return &Blame{
-		Repo:  t.repo,
 		Path:  t.path,
-		Rev:   t.rev,
+		Rev:   core.NewHash(t.rev),
 		Lines: blamedLines,
 	}
 }
 
 // run a blame on all the suite's tests
-func (s *SuiteCommon) TestBlame(c *C) {
-	for i, t := range blameTests {
+func (s *BlameCommon) TestBlame(c *C) {
+	for _, t := range blameTests {
 		expected := s.mockBlame(t, c)
 
 		repo, ok := s.repos[t.repo]
@@ -103,22 +89,12 @@
 		commit, err := repo.Commit(core.NewHash(t.rev))
 		c.Assert(err, IsNil)
 
-		obtained, err := New(repo, t.path, commit)
-		c.Assert(err, IsNil, Commentf("subtest %d", i))
-
-		c.Assert(obtained, DeepEquals, expected, Commentf("subtest %d: %s",
-			i, sideBySide(obtained, expected)))
+		obtained, err := commit.Blame(t.path)
+		c.Assert(err, IsNil)
+		c.Assert(obtained, DeepEquals, expected)
 	}
 }
 
-func sideBySide(output, expected *Blame) string {
-	var buf bytes.Buffer
-	buf.WriteString(output.Repo)
-	buf.WriteString("    ")
-	buf.WriteString(expected.Repo)
-	return buf.String()
-}
-
 // utility function to avoid writing so many repeated commits
 func repeat(s string, n int) []string {
 	if n < 0 {
diff --git a/clients/ssh/git_upload_pack_test.go b/clients/ssh/git_upload_pack_test.go
index 62a8596..66ac306 100644
--- a/clients/ssh/git_upload_pack_test.go
+++ b/clients/ssh/git_upload_pack_test.go
@@ -25,7 +25,6 @@
 )
 
 func (s *SuiteRemote) TestConnect(c *C) {
-	fmt.Println("TestConnect")
 	r := NewGitUploadPackService()
 	c.Assert(r.Connect(fixRepo), Equals, ErrAuthRequired)
 }
@@ -59,7 +58,6 @@
 }
 
 func (s *SuiteRemote) TestConnectWithPublicKeysCallback(c *C) {
-	fmt.Println("TestConnectWithPublicKeysCallback")
 	agent, err := newSSHAgentConn()
 	c.Assert(err, IsNil)
 	defer func() { c.Assert(agent.close(), IsNil) }()
@@ -72,19 +70,16 @@
 }
 
 func (s *SuiteRemote) TestConnectBadVcs(c *C) {
-	fmt.Println("TestConnectBadVcs")
 	r := NewGitUploadPackService()
 	c.Assert(r.ConnectWithAuth(fixRepoBadVcs, nil), ErrorMatches, fmt.Sprintf(".*%s.*", fixRepoBadVcs))
 }
 
 func (s *SuiteRemote) TestConnectNonGit(c *C) {
-	fmt.Println("TestConnectNonGit")
 	r := NewGitUploadPackService()
 	c.Assert(r.ConnectWithAuth(fixRepoNonGit, nil), Equals, ErrUnsupportedVCS)
 }
 
 func (s *SuiteRemote) TestConnectNonGithub(c *C) {
-	fmt.Println("TestConnectNonGit")
 	r := NewGitUploadPackService()
 	c.Assert(r.ConnectWithAuth(fixGitRepoNonGithub, nil), Equals, ErrUnsupportedRepo)
 }
@@ -97,14 +92,12 @@
 func (*mockAuth) String() string { return "" }
 
 func (s *SuiteRemote) TestConnectWithAuthWrongType(c *C) {
-	fmt.Println("TestConnectWithAuthWrongType")
 	r := NewGitUploadPackService()
 	c.Assert(r.ConnectWithAuth(fixRepo, &mockAuth{}), Equals, ErrInvalidAuthMethod)
 	c.Assert(r.connected, Equals, false)
 }
 
 func (s *SuiteRemote) TestAlreadyConnected(c *C) {
-	fmt.Println("TestAlreadyConnected")
 	agent, err := newSSHAgentConn()
 	c.Assert(err, IsNil)
 	defer func() { c.Assert(agent.close(), IsNil) }()
@@ -117,7 +110,6 @@
 }
 
 func (s *SuiteRemote) TestDisconnect(c *C) {
-	fmt.Println("TestDisconnect")
 	agent, err := newSSHAgentConn()
 	c.Assert(err, IsNil)
 	defer func() { c.Assert(agent.close(), IsNil) }()
@@ -129,13 +121,11 @@
 }
 
 func (s *SuiteRemote) TestDisconnectedWhenNonConnected(c *C) {
-	fmt.Println("TestDisconnectedWhenNonConnected")
 	r := NewGitUploadPackService()
 	c.Assert(r.Disconnect(), Equals, ErrNotConnected)
 }
 
 func (s *SuiteRemote) TestAlreadyDisconnected(c *C) {
-	fmt.Println("TestAlreadyDisconnected")
 	agent, err := newSSHAgentConn()
 	c.Assert(err, IsNil)
 	defer func() { c.Assert(agent.close(), IsNil) }()
@@ -148,7 +138,6 @@
 }
 
 func (s *SuiteRemote) TestServeralConnections(c *C) {
-	fmt.Println("TestServeralConnections")
 	agent, err := newSSHAgentConn()
 	c.Assert(err, IsNil)
 	defer func() { c.Assert(agent.close(), IsNil) }()
@@ -169,14 +158,12 @@
 }
 
 func (s *SuiteRemote) TestInfoNotConnected(c *C) {
-	fmt.Println("TestInfoNotConnected")
 	r := NewGitUploadPackService()
 	_, err := r.Info()
 	c.Assert(err, Equals, ErrNotConnected)
 }
 
 func (s *SuiteRemote) TestDefaultBranch(c *C) {
-	fmt.Println("TestDefaultBranch")
 	agent, err := newSSHAgentConn()
 	c.Assert(err, IsNil)
 	defer func() { c.Assert(agent.close(), IsNil) }()
@@ -191,7 +178,6 @@
 }
 
 func (s *SuiteRemote) TestCapabilities(c *C) {
-	fmt.Println("TestCapabilities")
 	agent, err := newSSHAgentConn()
 	c.Assert(err, IsNil)
 	defer func() { c.Assert(agent.close(), IsNil) }()
@@ -206,7 +192,6 @@
 }
 
 func (s *SuiteRemote) TestFetchNotConnected(c *C) {
-	fmt.Println("TestFetchNotConnected")
 	r := NewGitUploadPackService()
 	pr := &common.GitUploadPackRequest{}
 	pr.Want(core.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
@@ -215,7 +200,6 @@
 }
 
 func (s *SuiteRemote) TestFetch(c *C) {
-	fmt.Println("TestFetch")
 	agent, err := newSSHAgentConn()
 	c.Assert(err, IsNil)
 	defer func() { c.Assert(agent.close(), IsNil) }()
diff --git a/commit.go b/commit.go
index 99dbf37..1dd09ab 100644
--- a/commit.go
+++ b/commit.go
@@ -6,6 +6,7 @@
 	"errors"
 	"fmt"
 	"io"
+	"sort"
 
 	"gopkg.in/src-d/go-git.v2/core"
 )
@@ -159,3 +160,25 @@
 	defer func() { i.IsClosed = true }()
 	close(i.ch)
 }
+
+type commitSorterer struct {
+	l []*Commit
+}
+
+func (s commitSorterer) Len() int {
+	return len(s.l)
+}
+
+func (s commitSorterer) Less(i, j int) bool {
+	return s.l[i].Committer.When.Before(s.l[j].Committer.When)
+}
+
+func (s commitSorterer) Swap(i, j int) {
+	s.l[i], s.l[j] = s.l[j], s.l[i]
+}
+
+// SortCommits sort a commit list by commit date, from older to newer.
+func SortCommits(l []*Commit) {
+	s := &commitSorterer{l}
+	sort.Sort(s)
+}
diff --git a/common.go b/common.go
index 51486b8..6174339 100644
--- a/common.go
+++ b/common.go
@@ -2,17 +2,19 @@
 
 import "strings"
 
-// CountLines returns the number of lines in a string à la git, this is
+// countLines returns the number of lines in a string à la git, this is
 // The newline character is assumed to be '\n'.  The empty string
 // contains 0 lines.  If the last line of the string doesn't end with a
 // newline, it will still be considered a line.
-func CountLines(s string) int {
+func countLines(s string) int {
 	if s == "" {
 		return 0
 	}
-	nEol := strings.Count(s, "\n")
+
+	nEOL := strings.Count(s, "\n")
 	if strings.HasSuffix(s, "\n") {
-		return nEol
+		return nEOL
 	}
-	return nEol + 1
+
+	return nEOL + 1
 }
diff --git a/common_test.go b/common_test.go
index 4c48419..44b76ee 100644
--- a/common_test.go
+++ b/common_test.go
@@ -44,6 +44,15 @@
 	return r, nil
 }
 
+var fixtureRepos = [...]struct {
+	url      string
+	packfile string
+}{
+	{"https://github.com/tyba/git-fixture.git", "formats/packfile/fixtures/git-fixture.ofs-delta"},
+	{"https://github.com/jamesob/desk.git", "formats/packfile/fixtures/jamesob-desk.pack"},
+	{"https://github.com/spinnaker/spinnaker.git", "formats/packfile/fixtures/spinnaker-spinnaker.pack"},
+}
+
 type SuiteCommon struct{}
 
 var _ = Suite(&SuiteCommon{})
@@ -65,7 +74,7 @@
 
 func (s *SuiteCommon) TestCountLines(c *C) {
 	for i, t := range countLinesTests {
-		o := CountLines(t.i)
+		o := countLines(t.i)
 		c.Assert(o, Equals, t.e, Commentf("subtest %d, input=%q", i, t.i))
 	}
 }
diff --git a/objects_test.go b/objects_test.go
index a51f372..1ead65d 100644
--- a/objects_test.go
+++ b/objects_test.go
@@ -1,7 +1,6 @@
 package git
 
 import (
-	"fmt"
 	"io/ioutil"
 	"time"
 
@@ -128,7 +127,6 @@
 	}
 
 	for raw, exp := range cases {
-		fmt.Println("> testing", raw)
 		got := &Signature{}
 		got.Decode([]byte(raw))
 
diff --git a/revlist/revlist.go b/references.go
similarity index 68%
rename from revlist/revlist.go
rename to references.go
index bbc7e1f..0c57df9 100644
--- a/revlist/revlist.go
+++ b/references.go
@@ -15,74 +15,42 @@
 //
 // Another way to get the revision history for a file is:
 // git log --follow -p -- file
-package revlist
+package git
 
 import (
-	"bytes"
 	"io"
-	"sort"
 
-	"gopkg.in/src-d/go-git.v2"
 	"gopkg.in/src-d/go-git.v2/core"
 	"gopkg.in/src-d/go-git.v2/diff"
 
 	"github.com/sergi/go-diff/diffmatchpatch"
 )
 
-// A Revs is a list of revisions for a file (basically a list of commits).
-// It implements sort.Interface using the commit time.
-type Revs []*git.Commit
-
-func (l Revs) Len() int {
-	return len(l)
-}
-
-// sorts from older to newer commit.
-func (l Revs) Less(i, j int) bool {
-	return l[i].Committer.When.Before(l[j].Committer.When)
-}
-
-func (l Revs) Swap(i, j int) {
-	l[i], l[j] = l[j], l[i]
-}
-
-// for debugging
-func (l Revs) GoString() string {
-	var buf bytes.Buffer
-	for _, c := range l {
-		buf.WriteString(c.Hash.String()[:8])
-		buf.WriteString("\n")
-	}
-	return buf.String()
-}
-
-// NewRevs returns a Revs pointer for the
-// file at "path", from commit "commit".
-// The commits are sorted in commit order.
-// It stops searching a branch for a file upon reaching the commit
-// were the file was created.
-// Moves and copies are not currently supported.
-// Cherry-picks are not detected unless there are no commits between
-// them and therefore can appear repeated in the list.
-// (see git path-id for hints on how to fix this).
-func NewRevs(repo *git.Repository, commit *git.Commit, path string) (Revs, error) {
-	result := make(Revs, 0)
+// References returns a References for the file at "path", the commits are
+// sorted in commit order. It stops searching a branch for a file upon reaching
+// the commit were the file was created.
+//
+// Caveats:
+// - Moves and copies are not currently supported.
+// - Cherry-picks are not detected unless there are no commits between them and
+//   therefore can appear repeated in the list.
+//   (see git path-id for hints on how to fix this).
+func (c *Commit) References(path string) ([]*Commit, error) {
+	result := make([]*Commit, 0)
 	seen := make(map[core.Hash]struct{}, 0)
-	err := walkGraph(&result, &seen, repo, commit, path)
-	if err != nil {
+	if err := walkGraph(&result, &seen, c.r, c, path); err != nil {
 		return nil, err
 	}
-	sort.Sort(result)
-	result, err = removeComp(path, result, equivalent) // for merges of identical cherry-picks
-	if err != nil {
-		return nil, err
-	}
-	return result, nil
+
+	SortCommits(result)
+
+	// for merges of identical cherry-picks
+	return removeComp(path, result, equivalent)
 }
 
 // Recursive traversal of the commit graph, generating a linear history
 // of the path.
-func walkGraph(result *Revs, seen *map[core.Hash]struct{}, repo *git.Repository, current *git.Commit, path string) error {
+func walkGraph(result *[]*Commit, seen *map[core.Hash]struct{}, repo *Repository, current *Commit, path string) error {
 	// check and update seen
 	if _, ok := (*seen)[current.Hash]; ok {
 		return nil
@@ -132,8 +100,8 @@
 
 // TODO: benchmark this making git.Commit.parent public instead of using
 // an iterator
-func parentsContainingPath(path string, c *git.Commit) []*git.Commit {
-	var result []*git.Commit
+func parentsContainingPath(path string, c *Commit) []*Commit {
+	var result []*Commit
 	iter := c.Parents()
 	for {
 		parent, err := iter.Next()
@@ -151,11 +119,11 @@
 
 // Returns an slice of the commits in "cs" that has the file "path", but with different
 // contents than what can be found in "c".
-func differentContents(path string, c *git.Commit, cs []*git.Commit) ([]*git.Commit, error) {
-	result := make([]*git.Commit, 0, len(cs))
+func differentContents(path string, c *Commit, cs []*Commit) ([]*Commit, error) {
+	result := make([]*Commit, 0, len(cs))
 	h, found := blobHash(path, c)
 	if !found {
-		return nil, git.ErrFileNotFound
+		return nil, ErrFileNotFound
 	}
 	for _, cx := range cs {
 		if hx, found := blobHash(path, cx); found && h != hx {
@@ -166,7 +134,7 @@
 }
 
 // blobHash returns the hash of a path in a commit
-func blobHash(path string, commit *git.Commit) (hash core.Hash, found bool) {
+func blobHash(path string, commit *Commit) (hash core.Hash, found bool) {
 	file, err := commit.File(path)
 	if err != nil {
 		var empty core.Hash
@@ -175,13 +143,13 @@
 	return file.Hash, true
 }
 
-type contentsComparatorFn func(path string, a, b *git.Commit) (bool, error)
+type contentsComparatorFn func(path string, a, b *Commit) (bool, error)
 
 // Returns a new slice of commits, with duplicates removed.  Expects a
 // sorted commit list.  Duplication is defined according to "comp".  It
 // will always keep the first commit of a series of duplicated commits.
-func removeComp(path string, cs []*git.Commit, comp contentsComparatorFn) ([]*git.Commit, error) {
-	result := make([]*git.Commit, 0, len(cs))
+func removeComp(path string, cs []*Commit, comp contentsComparatorFn) ([]*Commit, error) {
+	result := make([]*Commit, 0, len(cs))
 	if len(cs) == 0 {
 		return result, nil
 	}
@@ -199,7 +167,7 @@
 }
 
 // Equivalent commits are commits whose patch is the same.
-func equivalent(path string, a, b *git.Commit) (bool, error) {
+func equivalent(path string, a, b *Commit) (bool, error) {
 	numParentsA := a.NumParents()
 	numParentsB := b.NumParents()
 
@@ -221,7 +189,7 @@
 	return sameDiffs(diffsA, diffsB), nil
 }
 
-func patch(c *git.Commit, path string) ([]diffmatchpatch.Diff, error) {
+func patch(c *Commit, path string) ([]diffmatchpatch.Diff, error) {
 	// get contents of the file in the commit
 	file, err := c.File(path)
 	if err != nil {
@@ -265,7 +233,7 @@
 	}
 	switch a.Type {
 	case 0:
-		return git.CountLines(a.Text) == git.CountLines(b.Text)
+		return countLines(a.Text) == countLines(b.Text)
 	case 1, -1:
 		return a.Text == b.Text
 	default:
diff --git a/revlist/revlist_test.go b/references_test.go
similarity index 90%
rename from revlist/revlist_test.go
rename to references_test.go
index 2fe7c83..ddc1e05 100644
--- a/revlist/revlist_test.go
+++ b/references_test.go
@@ -1,40 +1,27 @@
-package revlist
+package git
 
 import (
 	"bytes"
 	"fmt"
 	"os"
-	"testing"
 
-	"gopkg.in/src-d/go-git.v2"
 	"gopkg.in/src-d/go-git.v2/core"
 	"gopkg.in/src-d/go-git.v2/formats/packfile"
 
 	. "gopkg.in/check.v1"
 )
 
-func Test(t *testing.T) { TestingT(t) }
-
-type SuiteCommon struct {
-	repos map[string]*git.Repository
+type ReferencesSuite struct {
+	repos map[string]*Repository
 }
 
-var _ = Suite(&SuiteCommon{})
-
-var fixtureRepos = [...]struct {
-	url      string
-	packfile string
-}{
-	{"https://github.com/tyba/git-fixture.git", "../formats/packfile/fixtures/git-fixture.ofs-delta"},
-	{"https://github.com/jamesob/desk.git", "../formats/packfile/fixtures/jamesob-desk.pack"},
-	{"https://github.com/spinnaker/spinnaker.git", "../formats/packfile/fixtures/spinnaker-spinnaker.pack"},
-}
+var _ = Suite(&ReferencesSuite{})
 
 // create the repositories of the fixtures
-func (s *SuiteCommon) SetUpSuite(c *C) {
-	s.repos = make(map[string]*git.Repository, 0)
+func (s *ReferencesSuite) SetUpSuite(c *C) {
+	s.repos = make(map[string]*Repository, 0)
 	for _, fixRepo := range fixtureRepos {
-		s.repos[fixRepo.url] = git.NewPlainRepository()
+		s.repos[fixRepo.url] = NewPlainRepository()
 
 		d, err := os.Open(fixRepo.packfile)
 		defer d.Close()
@@ -48,7 +35,7 @@
 	}
 }
 
-var revListTests = [...]struct {
+var referencesTests = [...]struct {
 	// input data to revlist
 	repo   string
 	commit string
@@ -318,20 +305,18 @@
 	*/
 }
 
-func (s *SuiteCommon) TestRevList(c *C) {
-	for _, t := range revListTests {
+func (s *ReferencesSuite) TestRevList(c *C) {
+	for _, t := range referencesTests {
 		repo, ok := s.repos[t.repo]
 		c.Assert(ok, Equals, true)
 
 		commit, err := repo.Commit(core.NewHash(t.commit))
 		c.Assert(err, IsNil)
 
-		revs, err := NewRevs(repo, commit, t.path)
-		c.Assert(err, IsNil, Commentf("\nrepo=%s, commit=%s, path=%s\n",
-			t.repo, t.commit, t.path))
+		revs, err := commit.References(t.path)
+		c.Assert(err, IsNil)
+		c.Assert(len(revs), Equals, len(t.revs))
 
-		c.Assert(len(revs), Equals, len(t.revs), Commentf("\nrepo=%s, commit=%s, path=%s\n    EXPECTED (len %d)\n%s\n    OBTAINED (len %d)\n%s\n",
-			t.repo, t.commit, t.path, len(t.revs), t.revs, len(revs), revs.GoString()))
 		for i := range revs {
 			if revs[i].Hash.String() != t.revs[i] {
 				commit, err := repo.Commit(core.NewHash(t.revs[i]))
@@ -346,13 +331,11 @@
 				}
 			}
 		}
-		fmt.Printf("OK repo=%s, commit=%s, path=%s\n",
-			t.repo, t.commit, t.path)
 	}
 }
 
 // same length is assumed
-func compareSideBySide(a []string, b []*git.Commit) string {
+func compareSideBySide(a []string, b []*Commit) string {
 	var buf bytes.Buffer
 	buf.WriteString("\t              EXPECTED                                          OBTAINED        ")
 	var sep string
@@ -379,7 +362,7 @@
 }
 
 // should detect cherry picks
-func (s *SuiteCommon) TestEquivalent(c *C) {
+func (s *ReferencesSuite) TestEquivalent(c *C) {
 	for _, t := range cherryPicks {
 		cs := s.commits(c, t[0], t[2], t[3])
 		equiv, err := equivalent(t[1], cs[0], cs[1])
@@ -389,10 +372,10 @@
 }
 
 // returns the commits from a slice of hashes
-func (s *SuiteCommon) commits(cc *C, repo string, hs ...string) []*git.Commit {
+func (s *ReferencesSuite) commits(cc *C, repo string, hs ...string) []*Commit {
 	r, ok := s.repos[repo]
 	cc.Assert(ok, Equals, true)
-	result := make([]*git.Commit, 0, len(hs))
+	result := make([]*Commit, 0, len(hs))
 	for _, h := range hs {
 		c, err := r.Commit(core.NewHash(h))
 		cc.Assert(err, IsNil)
diff --git a/blame/blame2humantest.bash b/utils/blame2humantest.bash
similarity index 100%
rename from blame/blame2humantest.bash
rename to utils/blame2humantest.bash
diff --git a/revlist/revlist2humantest.bash b/utils/revlist2humantest.bash
similarity index 100%
rename from revlist/revlist2humantest.bash
rename to utils/revlist2humantest.bash