diff options
author | Máximo Cuadros <mcuadros@gmail.com> | 2017-09-12 14:22:10 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-12 14:22:10 +0200 |
commit | 7d1595faba108f5c6c9b678288eb5092ba555bd1 (patch) | |
tree | 96bb055b1ffd5cea41af7c0207399c44e2e246d8 /plumbing/revlist/revlist.go | |
parent | 8cb0215282c329d299d7d1d195abae4704981ba6 (diff) | |
parent | 5bb64f6220bd3c3c985efbc148e3f7253b3d9d71 (diff) | |
download | go-git-7d1595faba108f5c6c9b678288eb5092ba555bd1.tar.gz |
Merge pull request #588 from erizocosmico/perf/revlist-norevisit-ancestors-fixed
revlist: do not revisit ancestors as long as all branches are visited
Diffstat (limited to 'plumbing/revlist/revlist.go')
-rw-r--r-- | plumbing/revlist/revlist.go | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/plumbing/revlist/revlist.go b/plumbing/revlist/revlist.go index 009fc93..0a9d1e8 100644 --- a/plumbing/revlist/revlist.go +++ b/plumbing/revlist/revlist.go @@ -37,6 +37,7 @@ func objects( ) ([]plumbing.Hash, error) { seen := hashListToSet(ignore) result := make(map[plumbing.Hash]bool) + visited := make(map[plumbing.Hash]bool) walkerFunc := func(h plumbing.Hash) { if !seen[h] { @@ -46,7 +47,7 @@ func objects( } for _, h := range objects { - if err := processObject(s, h, seen, ignore, walkerFunc); err != nil { + if err := processObject(s, h, seen, visited, ignore, walkerFunc); err != nil { if allowMissingObjects && err == plumbing.ErrObjectNotFound { continue } @@ -63,6 +64,7 @@ func processObject( s storer.EncodedObjectStorer, h plumbing.Hash, seen map[plumbing.Hash]bool, + visited map[plumbing.Hash]bool, ignore []plumbing.Hash, walkerFunc func(h plumbing.Hash), ) error { @@ -82,12 +84,12 @@ func processObject( switch do := do.(type) { case *object.Commit: - return reachableObjects(do, seen, ignore, walkerFunc) + return reachableObjects(do, seen, visited, ignore, walkerFunc) case *object.Tree: return iterateCommitTrees(seen, do, walkerFunc) case *object.Tag: walkerFunc(do.Hash) - return processObject(s, do.Target, seen, ignore, walkerFunc) + return processObject(s, do.Target, seen, visited, ignore, walkerFunc) case *object.Blob: walkerFunc(do.Hash) default: @@ -105,10 +107,14 @@ func processObject( func reachableObjects( commit *object.Commit, seen map[plumbing.Hash]bool, + visited map[plumbing.Hash]bool, ignore []plumbing.Hash, cb func(h plumbing.Hash), ) error { i := object.NewCommitPreorderIter(commit, seen, ignore) + pending := make(map[plumbing.Hash]bool) + addPendingParents(pending, visited, commit) + for { commit, err := i.Next() if err == io.EOF { @@ -119,6 +125,16 @@ func reachableObjects( return err } + if pending[commit.Hash] { + delete(pending, commit.Hash) + } + + addPendingParents(pending, visited, commit) + + if visited[commit.Hash] && len(pending) == 0 { + break + } + if seen[commit.Hash] { continue } @@ -138,6 +154,14 @@ func reachableObjects( return nil } +func addPendingParents(pending, visited map[plumbing.Hash]bool, commit *object.Commit) { + for _, p := range commit.ParentHashes { + if !visited[p] { + pending[p] = true + } + } +} + // iterateCommitTrees iterate all reachable trees from the given commit func iterateCommitTrees( seen map[plumbing.Hash]bool, |