mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Integrate public as bindata optionally (#293)
* Dropped unused codekit config * Integrated dynamic and static bindata for public * Ignore public bindata * Add a general generate make task * Integrated flexible public assets into web command * Updated vendoring, added all missiong govendor deps * Made the linter happy with the bindata and dynamic code * Moved public bindata definition to modules directory * Ignoring the new bindata path now * Updated to the new public modules import path * Updated public bindata command and drop the new prefix
This commit is contained in:
		
				
					committed by
					
						 Lunny Xiao
						Lunny Xiao
					
				
			
			
				
	
			
			
			
						parent
						
							4680c349dd
						
					
				
				
					commit
					b6a95a8cb3
				
			
							
								
								
									
										400
									
								
								vendor/github.com/boltdb/bolt/cursor.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										400
									
								
								vendor/github.com/boltdb/bolt/cursor.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,400 @@ | ||||
| package bolt | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"fmt" | ||||
| 	"sort" | ||||
| ) | ||||
|  | ||||
| // Cursor represents an iterator that can traverse over all key/value pairs in a bucket in sorted order. | ||||
| // Cursors see nested buckets with value == nil. | ||||
| // Cursors can be obtained from a transaction and are valid as long as the transaction is open. | ||||
| // | ||||
| // Keys and values returned from the cursor are only valid for the life of the transaction. | ||||
| // | ||||
| // Changing data while traversing with a cursor may cause it to be invalidated | ||||
| // and return unexpected keys and/or values. You must reposition your cursor | ||||
| // after mutating data. | ||||
| type Cursor struct { | ||||
| 	bucket *Bucket | ||||
| 	stack  []elemRef | ||||
| } | ||||
|  | ||||
| // Bucket returns the bucket that this cursor was created from. | ||||
| func (c *Cursor) Bucket() *Bucket { | ||||
| 	return c.bucket | ||||
| } | ||||
|  | ||||
| // First moves the cursor to the first item in the bucket and returns its key and value. | ||||
| // If the bucket is empty then a nil key and value are returned. | ||||
| // The returned key and value are only valid for the life of the transaction. | ||||
| func (c *Cursor) First() (key []byte, value []byte) { | ||||
| 	_assert(c.bucket.tx.db != nil, "tx closed") | ||||
| 	c.stack = c.stack[:0] | ||||
| 	p, n := c.bucket.pageNode(c.bucket.root) | ||||
| 	c.stack = append(c.stack, elemRef{page: p, node: n, index: 0}) | ||||
| 	c.first() | ||||
|  | ||||
| 	// If we land on an empty page then move to the next value. | ||||
| 	// https://github.com/boltdb/bolt/issues/450 | ||||
| 	if c.stack[len(c.stack)-1].count() == 0 { | ||||
| 		c.next() | ||||
| 	} | ||||
|  | ||||
| 	k, v, flags := c.keyValue() | ||||
| 	if (flags & uint32(bucketLeafFlag)) != 0 { | ||||
| 		return k, nil | ||||
| 	} | ||||
| 	return k, v | ||||
|  | ||||
| } | ||||
|  | ||||
| // Last moves the cursor to the last item in the bucket and returns its key and value. | ||||
| // If the bucket is empty then a nil key and value are returned. | ||||
| // The returned key and value are only valid for the life of the transaction. | ||||
| func (c *Cursor) Last() (key []byte, value []byte) { | ||||
| 	_assert(c.bucket.tx.db != nil, "tx closed") | ||||
| 	c.stack = c.stack[:0] | ||||
| 	p, n := c.bucket.pageNode(c.bucket.root) | ||||
| 	ref := elemRef{page: p, node: n} | ||||
| 	ref.index = ref.count() - 1 | ||||
| 	c.stack = append(c.stack, ref) | ||||
| 	c.last() | ||||
| 	k, v, flags := c.keyValue() | ||||
| 	if (flags & uint32(bucketLeafFlag)) != 0 { | ||||
| 		return k, nil | ||||
| 	} | ||||
| 	return k, v | ||||
| } | ||||
|  | ||||
| // Next moves the cursor to the next item in the bucket and returns its key and value. | ||||
| // If the cursor is at the end of the bucket then a nil key and value are returned. | ||||
| // The returned key and value are only valid for the life of the transaction. | ||||
| func (c *Cursor) Next() (key []byte, value []byte) { | ||||
| 	_assert(c.bucket.tx.db != nil, "tx closed") | ||||
| 	k, v, flags := c.next() | ||||
| 	if (flags & uint32(bucketLeafFlag)) != 0 { | ||||
| 		return k, nil | ||||
| 	} | ||||
| 	return k, v | ||||
| } | ||||
|  | ||||
| // Prev moves the cursor to the previous item in the bucket and returns its key and value. | ||||
| // If the cursor is at the beginning of the bucket then a nil key and value are returned. | ||||
| // The returned key and value are only valid for the life of the transaction. | ||||
| func (c *Cursor) Prev() (key []byte, value []byte) { | ||||
| 	_assert(c.bucket.tx.db != nil, "tx closed") | ||||
|  | ||||
| 	// Attempt to move back one element until we're successful. | ||||
| 	// Move up the stack as we hit the beginning of each page in our stack. | ||||
| 	for i := len(c.stack) - 1; i >= 0; i-- { | ||||
| 		elem := &c.stack[i] | ||||
| 		if elem.index > 0 { | ||||
| 			elem.index-- | ||||
| 			break | ||||
| 		} | ||||
| 		c.stack = c.stack[:i] | ||||
| 	} | ||||
|  | ||||
| 	// If we've hit the end then return nil. | ||||
| 	if len(c.stack) == 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	// Move down the stack to find the last element of the last leaf under this branch. | ||||
| 	c.last() | ||||
| 	k, v, flags := c.keyValue() | ||||
| 	if (flags & uint32(bucketLeafFlag)) != 0 { | ||||
| 		return k, nil | ||||
| 	} | ||||
| 	return k, v | ||||
| } | ||||
|  | ||||
| // Seek moves the cursor to a given key and returns it. | ||||
| // If the key does not exist then the next key is used. If no keys | ||||
| // follow, a nil key is returned. | ||||
| // The returned key and value are only valid for the life of the transaction. | ||||
| func (c *Cursor) Seek(seek []byte) (key []byte, value []byte) { | ||||
| 	k, v, flags := c.seek(seek) | ||||
|  | ||||
| 	// If we ended up after the last element of a page then move to the next one. | ||||
| 	if ref := &c.stack[len(c.stack)-1]; ref.index >= ref.count() { | ||||
| 		k, v, flags = c.next() | ||||
| 	} | ||||
|  | ||||
| 	if k == nil { | ||||
| 		return nil, nil | ||||
| 	} else if (flags & uint32(bucketLeafFlag)) != 0 { | ||||
| 		return k, nil | ||||
| 	} | ||||
| 	return k, v | ||||
| } | ||||
|  | ||||
| // Delete removes the current key/value under the cursor from the bucket. | ||||
| // Delete fails if current key/value is a bucket or if the transaction is not writable. | ||||
| func (c *Cursor) Delete() error { | ||||
| 	if c.bucket.tx.db == nil { | ||||
| 		return ErrTxClosed | ||||
| 	} else if !c.bucket.Writable() { | ||||
| 		return ErrTxNotWritable | ||||
| 	} | ||||
|  | ||||
| 	key, _, flags := c.keyValue() | ||||
| 	// Return an error if current value is a bucket. | ||||
| 	if (flags & bucketLeafFlag) != 0 { | ||||
| 		return ErrIncompatibleValue | ||||
| 	} | ||||
| 	c.node().del(key) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // seek moves the cursor to a given key and returns it. | ||||
| // If the key does not exist then the next key is used. | ||||
| func (c *Cursor) seek(seek []byte) (key []byte, value []byte, flags uint32) { | ||||
| 	_assert(c.bucket.tx.db != nil, "tx closed") | ||||
|  | ||||
| 	// Start from root page/node and traverse to correct page. | ||||
| 	c.stack = c.stack[:0] | ||||
| 	c.search(seek, c.bucket.root) | ||||
| 	ref := &c.stack[len(c.stack)-1] | ||||
|  | ||||
| 	// If the cursor is pointing to the end of page/node then return nil. | ||||
| 	if ref.index >= ref.count() { | ||||
| 		return nil, nil, 0 | ||||
| 	} | ||||
|  | ||||
| 	// If this is a bucket then return a nil value. | ||||
| 	return c.keyValue() | ||||
| } | ||||
|  | ||||
| // first moves the cursor to the first leaf element under the last page in the stack. | ||||
| func (c *Cursor) first() { | ||||
| 	for { | ||||
| 		// Exit when we hit a leaf page. | ||||
| 		var ref = &c.stack[len(c.stack)-1] | ||||
| 		if ref.isLeaf() { | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		// Keep adding pages pointing to the first element to the stack. | ||||
| 		var pgid pgid | ||||
| 		if ref.node != nil { | ||||
| 			pgid = ref.node.inodes[ref.index].pgid | ||||
| 		} else { | ||||
| 			pgid = ref.page.branchPageElement(uint16(ref.index)).pgid | ||||
| 		} | ||||
| 		p, n := c.bucket.pageNode(pgid) | ||||
| 		c.stack = append(c.stack, elemRef{page: p, node: n, index: 0}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // last moves the cursor to the last leaf element under the last page in the stack. | ||||
| func (c *Cursor) last() { | ||||
| 	for { | ||||
| 		// Exit when we hit a leaf page. | ||||
| 		ref := &c.stack[len(c.stack)-1] | ||||
| 		if ref.isLeaf() { | ||||
| 			break | ||||
| 		} | ||||
|  | ||||
| 		// Keep adding pages pointing to the last element in the stack. | ||||
| 		var pgid pgid | ||||
| 		if ref.node != nil { | ||||
| 			pgid = ref.node.inodes[ref.index].pgid | ||||
| 		} else { | ||||
| 			pgid = ref.page.branchPageElement(uint16(ref.index)).pgid | ||||
| 		} | ||||
| 		p, n := c.bucket.pageNode(pgid) | ||||
|  | ||||
| 		var nextRef = elemRef{page: p, node: n} | ||||
| 		nextRef.index = nextRef.count() - 1 | ||||
| 		c.stack = append(c.stack, nextRef) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // next moves to the next leaf element and returns the key and value. | ||||
| // If the cursor is at the last leaf element then it stays there and returns nil. | ||||
| func (c *Cursor) next() (key []byte, value []byte, flags uint32) { | ||||
| 	for { | ||||
| 		// Attempt to move over one element until we're successful. | ||||
| 		// Move up the stack as we hit the end of each page in our stack. | ||||
| 		var i int | ||||
| 		for i = len(c.stack) - 1; i >= 0; i-- { | ||||
| 			elem := &c.stack[i] | ||||
| 			if elem.index < elem.count()-1 { | ||||
| 				elem.index++ | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// If we've hit the root page then stop and return. This will leave the | ||||
| 		// cursor on the last element of the last page. | ||||
| 		if i == -1 { | ||||
| 			return nil, nil, 0 | ||||
| 		} | ||||
|  | ||||
| 		// Otherwise start from where we left off in the stack and find the | ||||
| 		// first element of the first leaf page. | ||||
| 		c.stack = c.stack[:i+1] | ||||
| 		c.first() | ||||
|  | ||||
| 		// If this is an empty page then restart and move back up the stack. | ||||
| 		// https://github.com/boltdb/bolt/issues/450 | ||||
| 		if c.stack[len(c.stack)-1].count() == 0 { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		return c.keyValue() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // search recursively performs a binary search against a given page/node until it finds a given key. | ||||
| func (c *Cursor) search(key []byte, pgid pgid) { | ||||
| 	p, n := c.bucket.pageNode(pgid) | ||||
| 	if p != nil && (p.flags&(branchPageFlag|leafPageFlag)) == 0 { | ||||
| 		panic(fmt.Sprintf("invalid page type: %d: %x", p.id, p.flags)) | ||||
| 	} | ||||
| 	e := elemRef{page: p, node: n} | ||||
| 	c.stack = append(c.stack, e) | ||||
|  | ||||
| 	// If we're on a leaf page/node then find the specific node. | ||||
| 	if e.isLeaf() { | ||||
| 		c.nsearch(key) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if n != nil { | ||||
| 		c.searchNode(key, n) | ||||
| 		return | ||||
| 	} | ||||
| 	c.searchPage(key, p) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) searchNode(key []byte, n *node) { | ||||
| 	var exact bool | ||||
| 	index := sort.Search(len(n.inodes), func(i int) bool { | ||||
| 		// TODO(benbjohnson): Optimize this range search. It's a bit hacky right now. | ||||
| 		// sort.Search() finds the lowest index where f() != -1 but we need the highest index. | ||||
| 		ret := bytes.Compare(n.inodes[i].key, key) | ||||
| 		if ret == 0 { | ||||
| 			exact = true | ||||
| 		} | ||||
| 		return ret != -1 | ||||
| 	}) | ||||
| 	if !exact && index > 0 { | ||||
| 		index-- | ||||
| 	} | ||||
| 	c.stack[len(c.stack)-1].index = index | ||||
|  | ||||
| 	// Recursively search to the next page. | ||||
| 	c.search(key, n.inodes[index].pgid) | ||||
| } | ||||
|  | ||||
| func (c *Cursor) searchPage(key []byte, p *page) { | ||||
| 	// Binary search for the correct range. | ||||
| 	inodes := p.branchPageElements() | ||||
|  | ||||
| 	var exact bool | ||||
| 	index := sort.Search(int(p.count), func(i int) bool { | ||||
| 		// TODO(benbjohnson): Optimize this range search. It's a bit hacky right now. | ||||
| 		// sort.Search() finds the lowest index where f() != -1 but we need the highest index. | ||||
| 		ret := bytes.Compare(inodes[i].key(), key) | ||||
| 		if ret == 0 { | ||||
| 			exact = true | ||||
| 		} | ||||
| 		return ret != -1 | ||||
| 	}) | ||||
| 	if !exact && index > 0 { | ||||
| 		index-- | ||||
| 	} | ||||
| 	c.stack[len(c.stack)-1].index = index | ||||
|  | ||||
| 	// Recursively search to the next page. | ||||
| 	c.search(key, inodes[index].pgid) | ||||
| } | ||||
|  | ||||
| // nsearch searches the leaf node on the top of the stack for a key. | ||||
| func (c *Cursor) nsearch(key []byte) { | ||||
| 	e := &c.stack[len(c.stack)-1] | ||||
| 	p, n := e.page, e.node | ||||
|  | ||||
| 	// If we have a node then search its inodes. | ||||
| 	if n != nil { | ||||
| 		index := sort.Search(len(n.inodes), func(i int) bool { | ||||
| 			return bytes.Compare(n.inodes[i].key, key) != -1 | ||||
| 		}) | ||||
| 		e.index = index | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// If we have a page then search its leaf elements. | ||||
| 	inodes := p.leafPageElements() | ||||
| 	index := sort.Search(int(p.count), func(i int) bool { | ||||
| 		return bytes.Compare(inodes[i].key(), key) != -1 | ||||
| 	}) | ||||
| 	e.index = index | ||||
| } | ||||
|  | ||||
| // keyValue returns the key and value of the current leaf element. | ||||
| func (c *Cursor) keyValue() ([]byte, []byte, uint32) { | ||||
| 	ref := &c.stack[len(c.stack)-1] | ||||
| 	if ref.count() == 0 || ref.index >= ref.count() { | ||||
| 		return nil, nil, 0 | ||||
| 	} | ||||
|  | ||||
| 	// Retrieve value from node. | ||||
| 	if ref.node != nil { | ||||
| 		inode := &ref.node.inodes[ref.index] | ||||
| 		return inode.key, inode.value, inode.flags | ||||
| 	} | ||||
|  | ||||
| 	// Or retrieve value from page. | ||||
| 	elem := ref.page.leafPageElement(uint16(ref.index)) | ||||
| 	return elem.key(), elem.value(), elem.flags | ||||
| } | ||||
|  | ||||
| // node returns the node that the cursor is currently positioned on. | ||||
| func (c *Cursor) node() *node { | ||||
| 	_assert(len(c.stack) > 0, "accessing a node with a zero-length cursor stack") | ||||
|  | ||||
| 	// If the top of the stack is a leaf node then just return it. | ||||
| 	if ref := &c.stack[len(c.stack)-1]; ref.node != nil && ref.isLeaf() { | ||||
| 		return ref.node | ||||
| 	} | ||||
|  | ||||
| 	// Start from root and traverse down the hierarchy. | ||||
| 	var n = c.stack[0].node | ||||
| 	if n == nil { | ||||
| 		n = c.bucket.node(c.stack[0].page.id, nil) | ||||
| 	} | ||||
| 	for _, ref := range c.stack[:len(c.stack)-1] { | ||||
| 		_assert(!n.isLeaf, "expected branch node") | ||||
| 		n = n.childAt(int(ref.index)) | ||||
| 	} | ||||
| 	_assert(n.isLeaf, "expected leaf node") | ||||
| 	return n | ||||
| } | ||||
|  | ||||
| // elemRef represents a reference to an element on a given page/node. | ||||
| type elemRef struct { | ||||
| 	page  *page | ||||
| 	node  *node | ||||
| 	index int | ||||
| } | ||||
|  | ||||
| // isLeaf returns whether the ref is pointing at a leaf page/node. | ||||
| func (r *elemRef) isLeaf() bool { | ||||
| 	if r.node != nil { | ||||
| 		return r.node.isLeaf | ||||
| 	} | ||||
| 	return (r.page.flags & leafPageFlag) != 0 | ||||
| } | ||||
|  | ||||
| // count returns the number of inodes or page elements. | ||||
| func (r *elemRef) count() int { | ||||
| 	if r.node != nil { | ||||
| 		return len(r.node.inodes) | ||||
| 	} | ||||
| 	return int(r.page.count) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user