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

git rev-list command #757

Open
Dal-Papa opened this issue Feb 21, 2018 · 5 comments
Open

git rev-list command #757

Dal-Papa opened this issue Feb 21, 2018 · 5 comments

Comments

@Dal-Papa
Copy link

I wanted to reproduce the behavior of git rev-list HEAD my_file with the help of go-git.

As this feature was not here out of the box, I tried my best to do a clean implementation for it with the library and it looks like this :

cIter, err := g.Log(&git.LogOptions{
    From: fromHash,
})

history := make(map[string]CommitSlice) 
// Where CommitSlice is just an improved version of HashSlice which can sort by Commit date

err = cIter.ForEach(func(c *object.Commit) error {
    sts, err := c.Stats()
    if err != nil {
        if err != plumbing.ErrObjectNotFound {
            return err
        }
        files, err := c.Files()
        CheckIfErr(err)
        files.ForEach(func(f *object.File) error {
            history[f.Name] = append(history[f.Name], c.Hash)
            return nil
        })
    }
    for _, f := range sts {
        if c.NumParents() < 2 { // To get the actual commit and not the merge commit
            history[f.Name] = append(history[f.Name], c.Hash)
        }
    }
    return nil
})

// CommitSlice implementation of the sort.Interface striped from this example.

I'd like to share this with the community and potentially have it in the go-git library so I'm wondering what would be the best place for this to live in.

Thanks !

@mcuadros
Copy link
Contributor

The best place is the revlist package: https://godoc.org/gopkg.in/src-d/go-git.v4/plumbing/revlist
We need to figure out a proper API, Maybe adding an options to be able to filter by name and future implementations. The problem is I rather not modify the API, because otherwise, we need to release a new major.

Also maybe we can keep the revlist package as a low-level package and create a new method:
Repository.RevList(*RevListOptions)

@mcuadros
Copy link
Contributor

/cc @orirawlings @ajnavarro

@Dal-Papa
Copy link
Author

Dal-Papa commented Feb 26, 2018

@mcuadros : That sounds good to me, I can do that with just adding a new method as opposed to break compatibility with the old one. I also have the filtering mechanism for files in place so I'll add that. Thanks for the input.

@ghost
Copy link

ghost commented Nov 21, 2018

If we implement rev-list I would like to be able to see the amount of commits ahead and behind a local branch compared to its remote, for example equivalent of the following git command:

git rev-list --left-right --count origin/master..master
0	1

@isacikgoz
Copy link

Here is my revlist implementation:

It works fine except performance issue. The problem is; Can't get it work with one revlist.Objects() function. I need to calculate two times to get actual revlist.

// RevListOptions defines the rules of rev-list func
type RevListOptions struct {
	// Ref1 is the first reference hash to link
	Ref1 string
	// Ref2 is the second reference hash to link
	Ref2 string
}

// RevList is native implemetation of git rev-list command
func RevList(r *git.Repository, opts RevListOptions) ([]*object.Commit, error) {

	commits := make([]*object.Commit, 0)
	ref1hist, err := revlist.Objects(r.Storer, []plumbing.Hash{plumbing.NewHash(opts.Ref1)}, nil)
	if err != nil {
		return nil, err
	}
	ref2hist, err := revlist.Objects(r.Storer, []plumbing.Hash{plumbing.NewHash(opts.Ref2)}, ref1hist)
	if err != nil {
		return nil, err
	}

	for _, h := range ref2hist {
		c, err := r.CommitObject(h)
		if err != nil {
			continue
		}
		commits = append(commits, c)
	}
        // Basically sorts by date
	sort.Sort(CommitTime(commits))
	return commits, err
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants