mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-05-11 20:36:03 +02:00
fix reflog failing to properly refresh
This commit is contained in:
parent
f4ddf2f0d4
commit
ce3bcfe37c
16 changed files with 1196 additions and 3 deletions
167
vendor/github.com/sanity-io/litter/pointers.go
generated
vendored
Normal file
167
vendor/github.com/sanity-io/litter/pointers.go
generated
vendored
Normal file
|
@ -0,0 +1,167 @@
|
|||
package litter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// mapReusedPointers takes a structure, and recursively maps all pointers mentioned in the tree,
|
||||
// detecting circular references, and providing a list of all pointers that was referenced at
|
||||
// least twice by the provided structure.
|
||||
func mapReusedPointers(v reflect.Value) ptrmap {
|
||||
pm := &pointerVisitor{}
|
||||
pm.consider(v)
|
||||
return pm.reused
|
||||
}
|
||||
|
||||
// A map of pointers.
|
||||
type ptrinfo struct {
|
||||
id int
|
||||
parent *ptrmap
|
||||
}
|
||||
|
||||
func (p *ptrinfo) label() string {
|
||||
if p.id == -1 {
|
||||
p.id = p.parent.count
|
||||
p.parent.count++
|
||||
}
|
||||
return fmt.Sprintf("p%d", p.id)
|
||||
}
|
||||
|
||||
type ptrkey struct {
|
||||
p uintptr
|
||||
t reflect.Type
|
||||
}
|
||||
|
||||
func ptrkeyFor(v reflect.Value) (k ptrkey) {
|
||||
k.p = v.Pointer()
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.IsValid() {
|
||||
k.t = v.Type()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ptrmap struct {
|
||||
m map[ptrkey]*ptrinfo
|
||||
count int
|
||||
}
|
||||
|
||||
// Returns true if contains a pointer.
|
||||
func (pm *ptrmap) contains(v reflect.Value) bool {
|
||||
if pm.m != nil {
|
||||
_, ok := pm.m[ptrkeyFor(v)]
|
||||
return ok
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Gets a pointer.
|
||||
func (pm *ptrmap) get(v reflect.Value) (*ptrinfo, bool) {
|
||||
if pm.m != nil {
|
||||
p, ok := pm.m[ptrkeyFor(v)]
|
||||
return p, ok
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Removes a pointer.
|
||||
func (pm *ptrmap) remove(v reflect.Value) {
|
||||
if pm.m != nil {
|
||||
delete(pm.m, ptrkeyFor(v))
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a pointer.
|
||||
func (pm *ptrmap) add(p reflect.Value) bool {
|
||||
if pm.contains(p) {
|
||||
return false
|
||||
}
|
||||
pm.put(p)
|
||||
return true
|
||||
}
|
||||
|
||||
// Adds a pointer (slow path).
|
||||
func (pm *ptrmap) put(v reflect.Value) {
|
||||
if pm.m == nil {
|
||||
pm.m = make(map[ptrkey]*ptrinfo, 31)
|
||||
}
|
||||
|
||||
key := ptrkeyFor(v)
|
||||
if _, ok := pm.m[key]; !ok {
|
||||
pm.m[key] = &ptrinfo{id: -1, parent: pm}
|
||||
}
|
||||
}
|
||||
|
||||
type pointerVisitor struct {
|
||||
pointers ptrmap
|
||||
reused ptrmap
|
||||
}
|
||||
|
||||
// Recursively consider v and each of its children, updating the map according to the
|
||||
// semantics of MapReusedPointers
|
||||
func (pv *pointerVisitor) consider(v reflect.Value) {
|
||||
if v.Kind() == reflect.Invalid {
|
||||
return
|
||||
}
|
||||
if isPointerValue(v) { // pointer is 0 for unexported fields
|
||||
if pv.tryAddPointer(v) {
|
||||
// No use descending inside this value, since it have been seen before and all its descendants
|
||||
// have been considered
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Now descend into any children of this value
|
||||
switch v.Kind() {
|
||||
case reflect.Slice, reflect.Array:
|
||||
numEntries := v.Len()
|
||||
for i := 0; i < numEntries; i++ {
|
||||
pv.consider(v.Index(i))
|
||||
}
|
||||
|
||||
case reflect.Interface:
|
||||
pv.consider(v.Elem())
|
||||
|
||||
case reflect.Ptr:
|
||||
pv.consider(v.Elem())
|
||||
|
||||
case reflect.Map:
|
||||
keys := v.MapKeys()
|
||||
sort.Sort(mapKeySorter{
|
||||
keys: keys,
|
||||
options: &Config,
|
||||
})
|
||||
for _, key := range keys {
|
||||
pv.consider(v.MapIndex(key))
|
||||
}
|
||||
|
||||
case reflect.Struct:
|
||||
numFields := v.NumField()
|
||||
for i := 0; i < numFields; i++ {
|
||||
pv.consider(v.Field(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// addPointer to the pointerMap, update reusedPointers. Returns true if pointer was reused
|
||||
func (pv *pointerVisitor) tryAddPointer(v reflect.Value) bool {
|
||||
// Is this allready known to be reused?
|
||||
if pv.reused.contains(v) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Have we seen it once before?
|
||||
if pv.pointers.contains(v) {
|
||||
// Add it to the register of pointers we have seen more than once
|
||||
pv.reused.add(v)
|
||||
return true
|
||||
}
|
||||
|
||||
// This pointer was new to us
|
||||
pv.pointers.add(v)
|
||||
return false
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue