-
Notifications
You must be signed in to change notification settings - Fork 735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Git Log Revision Range #36
Comments
This requires a couple of developments:
PR's are welcome. |
A workaround I've used is repo, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
URL: "some-repo",
})
start, err := repo.ResolveRevision("start-sha")
check(err)
end, err := repo.ResolveRevision("end-sha")
check(err)
iter, err := repo.Log(&git.LogOptions{From: *end})
check(err)
err = iter.ForEach(func(c *object.Commit) error {
fmt.Println(c.Message)
if c.Hash == *start {
return storer.ErrStop
}
return nil
})
check(err) |
Hey! Based on @dprotaso code, I came up with this: An iterator, which expects 2
What I do I expect two package main
import (
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
)
type excludeCommitIter struct {
iter object.CommitIter
excludeIter object.CommitIter
excludeList map[plumbing.Hash]bool
}
func newExcludeCommitIter(iter object.CommitIter, excludeIter object.CommitIter) *excludeCommitIter {
out := excludeCommitIter{iter: iter, excludeIter: excludeIter}
out.excludeList = make(map[plumbing.Hash]bool)
return &out
}
func (iter *excludeCommitIter) init() {
if len(iter.excludeList) == 0 {
iter.excludeIter.ForEach(func(c *object.Commit) error {
iter.excludeList[c.Hash] = true
return nil
})
}
}
func (iter *excludeCommitIter) Next() (*object.Commit, error) {
iter.init()
obj, err := iter.iter.Next()
if err != nil {
return nil, err
}
if _, exists := iter.excludeList[obj.Hash]; !exists {
return obj, nil
}
return iter.Next()
}
func (iter *excludeCommitIter) ForEach(cb func(*object.Commit) error) error {
iter.init()
return iter.iter.ForEach(func(c *object.Commit) error {
if _, exists := iter.excludeList[c.Hash]; !exists {
return cb(c)
}
return nil
})
} Using this iterator I can get the list of changes between the my two branches. func gitLogRevision(sourcePath string, sourceRev plumbing.Revision, excludeRev plumbing.Revision) ([]string, error) {
r, err := git.PlainOpen(filepath.Join(sourcePath, ".git"))
if err != nil {
return nil, err
}
source, err := r.ResolveRevision(sourceRev)
if err != nil {
return nil, err
}
exclude, err := r.ResolveRevision(excludeRev)
if err != nil {
return nil, err
}
sourceIter, err := r.Log(&git.LogOptions{From: *source})
if err != nil {
return nil, err
}
excludeIter, err := r.Log(&git.LogOptions{From: *exclude})
if err != nil {
return nil, err
}
iter := newExcludeCommitIter(sourceIter, excludeIter)
var firstLines []string
err = iter.ForEach(func(c *object.Commit) error {
// git log --no-merges
if len(c.ParentHashes) > 1 {
return nil
}
// git log --format="%s", aka the first line of the commit message
firstLines = append(firstLines, strings.Split(c.Message, "\n")[0])
return nil
})
if err != nil {
return nil, err
}
return firstLines, nil
} It can be further improved, for example we can make it more general, "filterable iterator" and the filter function can be passed in, therefore any kind of filtering could be done. I'm still not sure that it's right, however on my test env it looks good. What do you think? |
It can be implemented even more simpler, by using the newFilterCommitIter seen := map[plumbing.Hash]struct{}{}
excludeIter.ForEach(func(c *object.Commit) error {
seen[c.Hash] = struct{}{}
return nil
})
var isValid object.CommitFilter = func(commit *object.Commit) bool {
_, ok := seen[commit.Hash]
// len(commit.ParentHashes) filters out merge commits
return !ok && len(commit.ParentHashes) < 2
}
iter := object.NewFilterCommitIter(sourceCommit, &isValid, nil) I don't know if is there a better way to see if a commit exists in a branch |
The implemented a way to get changes between two revisions Basicall what `git log foo..bar` would do. Extended `LogOptions`, so it accepts a `Except` Hash which defines what commits should be excluded from the final result. Hadling that flag, if exists we create a new iterator which called commitDifferenceIterator. That iterator expects a map of `Hash`es, which commits will be excluded from the final commit list. Thsi pr is related to issue go-git#36
issue defined: go-git/go-git#36 solution provided by: https://github.com/Ajnasz/go-git/ commit/ed33969b0b7994b593d1a36fc46f034791cafe6f
To help us keep things tidy and focus on the active tasks, we've introduced a stale bot to spot issues/PRs that haven't had any activity in a while. This particular issue hasn't had any updates or activity in the past 90 days, so it's been labeled as 'stale'. If it remains inactive for the next 30 days, it'll be automatically closed. We understand everyone's busy, but if this issue is still important to you, please feel free to add a comment or make an update to keep it active. Thanks for your understanding and cooperation! |
Found this old Issue on the old repo: src-d/go-git#1166.
It would be super useful for something like
git log HEAD..origin/master
to be added togit.LogOptions
as this would make working with Git Logs much easier.The text was updated successfully, but these errors were encountered: