mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-06-10 08:29:32 +00:00
Implement git refs API for listing references (branches, tags and other) (#5354)
* Inital routes to git refs api * Git refs API implementation * Update swagger * Fix copyright * Make swagger happy add basic test * Fix test * Fix test again :)
This commit is contained in:
parent
294904321c
commit
08bf443016
268 changed files with 48603 additions and 10 deletions
216
vendor/gopkg.in/src-d/go-git.v4/utils/merkletrie/iter.go
generated
vendored
Normal file
216
vendor/gopkg.in/src-d/go-git.v4/utils/merkletrie/iter.go
generated
vendored
Normal file
|
@ -0,0 +1,216 @@
|
|||
package merkletrie
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"gopkg.in/src-d/go-git.v4/utils/merkletrie/internal/frame"
|
||||
"gopkg.in/src-d/go-git.v4/utils/merkletrie/noder"
|
||||
)
|
||||
|
||||
// Iter is an iterator for merkletries (only the trie part of the
|
||||
// merkletrie is relevant here, it does not use the Hasher interface).
|
||||
//
|
||||
// The iteration is performed in depth-first pre-order. Entries at each
|
||||
// depth are traversed in (case-sensitive) alphabetical order.
|
||||
//
|
||||
// This is the kind of traversal you will expect when listing ordinary
|
||||
// files and directories recursively, for example:
|
||||
//
|
||||
// Trie Traversal order
|
||||
// ---- ---------------
|
||||
// .
|
||||
// / | \ c
|
||||
// / | \ d/
|
||||
// d c z ===> d/a
|
||||
// / \ d/b
|
||||
// b a z
|
||||
//
|
||||
//
|
||||
// This iterator is somewhat especial as you can chose to skip whole
|
||||
// "directories" when iterating:
|
||||
//
|
||||
// - The Step method will iterate normally.
|
||||
//
|
||||
// - the Next method will not descend deeper into the tree.
|
||||
//
|
||||
// For example, if the iterator is at `d/`, the Step method will return
|
||||
// `d/a` while the Next would have returned `z` instead (skipping `d/`
|
||||
// and its descendants). The name of the these two methods are based on
|
||||
// the well known "next" and "step" operations, quite common in
|
||||
// debuggers, like gdb.
|
||||
//
|
||||
// The paths returned by the iterator will be relative, if the iterator
|
||||
// was created from a single node, or absolute, if the iterator was
|
||||
// created from the path to the node (the path will be prefixed to all
|
||||
// returned paths).
|
||||
type Iter struct {
|
||||
// Tells if the iteration has started.
|
||||
hasStarted bool
|
||||
// The top of this stack has the current node and its siblings. The
|
||||
// rest of the stack keeps the ancestors of the current node and
|
||||
// their corresponding siblings. The current element is always the
|
||||
// top element of the top frame.
|
||||
//
|
||||
// When "step"ping into a node, its children are pushed as a new
|
||||
// frame.
|
||||
//
|
||||
// When "next"ing pass a node, the current element is dropped by
|
||||
// popping the top frame.
|
||||
frameStack []*frame.Frame
|
||||
// The base path used to turn the relative paths used internally by
|
||||
// the iterator into absolute paths used by external applications.
|
||||
// For relative iterator this will be nil.
|
||||
base noder.Path
|
||||
}
|
||||
|
||||
// NewIter returns a new relative iterator using the provider noder as
|
||||
// its unnamed root. When iterating, all returned paths will be
|
||||
// relative to node.
|
||||
func NewIter(n noder.Noder) (*Iter, error) {
|
||||
return newIter(n, nil)
|
||||
}
|
||||
|
||||
// NewIterFromPath returns a new absolute iterator from the noder at the
|
||||
// end of the path p. When iterating, all returned paths will be
|
||||
// absolute, using the root of the path p as their root.
|
||||
func NewIterFromPath(p noder.Path) (*Iter, error) {
|
||||
return newIter(p, p) // Path implements Noder
|
||||
}
|
||||
|
||||
func newIter(root noder.Noder, base noder.Path) (*Iter, error) {
|
||||
ret := &Iter{
|
||||
base: base,
|
||||
}
|
||||
|
||||
if root == nil {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
frame, err := frame.New(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret.push(frame)
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (iter *Iter) top() (*frame.Frame, bool) {
|
||||
if len(iter.frameStack) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
top := len(iter.frameStack) - 1
|
||||
|
||||
return iter.frameStack[top], true
|
||||
}
|
||||
|
||||
func (iter *Iter) push(f *frame.Frame) {
|
||||
iter.frameStack = append(iter.frameStack, f)
|
||||
}
|
||||
|
||||
const (
|
||||
doDescend = true
|
||||
dontDescend = false
|
||||
)
|
||||
|
||||
// Next returns the path of the next node without descending deeper into
|
||||
// the trie and nil. If there are no more entries in the trie it
|
||||
// returns nil and io.EOF. In case of error, it will return nil and the
|
||||
// error.
|
||||
func (iter *Iter) Next() (noder.Path, error) {
|
||||
return iter.advance(dontDescend)
|
||||
}
|
||||
|
||||
// Step returns the path to the next node in the trie, descending deeper
|
||||
// into it if needed, and nil. If there are no more nodes in the trie,
|
||||
// it returns nil and io.EOF. In case of error, it will return nil and
|
||||
// the error.
|
||||
func (iter *Iter) Step() (noder.Path, error) {
|
||||
return iter.advance(doDescend)
|
||||
}
|
||||
|
||||
// Advances the iterator in the desired direction: descend or
|
||||
// dontDescend.
|
||||
//
|
||||
// Returns the new current element and a nil error on success. If there
|
||||
// are no more elements in the trie below the base, it returns nil, and
|
||||
// io.EOF. Returns nil and an error in case of errors.
|
||||
func (iter *Iter) advance(wantDescend bool) (noder.Path, error) {
|
||||
current, err := iter.current()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The first time we just return the current node.
|
||||
if !iter.hasStarted {
|
||||
iter.hasStarted = true
|
||||
return current, nil
|
||||
}
|
||||
|
||||
// Advances means getting a next current node, either its first child or
|
||||
// its next sibling, depending if we must descend or not.
|
||||
numChildren, err := current.NumChildren()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mustDescend := numChildren != 0 && wantDescend
|
||||
if mustDescend {
|
||||
// descend: add a new frame with the current's children.
|
||||
frame, err := frame.New(current)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iter.push(frame)
|
||||
} else {
|
||||
// don't descend: just drop the current node
|
||||
iter.drop()
|
||||
}
|
||||
|
||||
return iter.current()
|
||||
}
|
||||
|
||||
// Returns the path to the current node, adding the base if there was
|
||||
// one, and a nil error. If there were no noders left, it returns nil
|
||||
// and io.EOF. If an error occurred, it returns nil and the error.
|
||||
func (iter *Iter) current() (noder.Path, error) {
|
||||
if topFrame, ok := iter.top(); !ok {
|
||||
return nil, io.EOF
|
||||
} else if _, ok := topFrame.First(); !ok {
|
||||
return nil, io.EOF
|
||||
}
|
||||
|
||||
ret := make(noder.Path, 0, len(iter.base)+len(iter.frameStack))
|
||||
|
||||
// concat the base...
|
||||
ret = append(ret, iter.base...)
|
||||
// ... and the current node and all its ancestors
|
||||
for i, f := range iter.frameStack {
|
||||
t, ok := f.First()
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("frame %d is empty", i))
|
||||
}
|
||||
ret = append(ret, t)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// removes the current node if any, and all the frames that become empty as a
|
||||
// consequence of this action.
|
||||
func (iter *Iter) drop() {
|
||||
frame, ok := iter.top()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
frame.Drop()
|
||||
// if the frame is empty, remove it and its parent, recursively
|
||||
if frame.Len() == 0 {
|
||||
top := len(iter.frameStack) - 1
|
||||
iter.frameStack[top] = nil
|
||||
iter.frameStack = iter.frameStack[:top]
|
||||
iter.drop()
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue