mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-19 06:54:58 +02:00
switch to a breadth first traversal
This commit is contained in:
@@ -66,7 +66,7 @@ type FileSystemScanner struct {
|
|||||||
root_dir string
|
root_dir string
|
||||||
mutex sync.Mutex
|
mutex sync.Mutex
|
||||||
results []ResultItem
|
results []ResultItem
|
||||||
dir_reader func(path string, level int) ([]fs.DirEntry, error)
|
dir_reader func(path string) ([]fs.DirEntry, error)
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,9 +74,7 @@ func NewFileSystemScanner(root_dir string, notify chan int) (fss *FileSystemScan
|
|||||||
ans := &FileSystemScanner{root_dir: root_dir, listeners: []chan int{notify}, results: make([]ResultItem, 0, 1024)}
|
ans := &FileSystemScanner{root_dir: root_dir, listeners: []chan int{notify}, results: make([]ResultItem, 0, 1024)}
|
||||||
ans.in_progress.Store(true)
|
ans.in_progress.Store(true)
|
||||||
ans.keep_going.Store(true)
|
ans.keep_going.Store(true)
|
||||||
ans.dir_reader = func(path string, level int) ([]fs.DirEntry, error) {
|
ans.dir_reader = os.ReadDir
|
||||||
return os.ReadDir(path)
|
|
||||||
}
|
|
||||||
return ans
|
return ans
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,69 +145,74 @@ func (fss *FileSystemScanner) worker() {
|
|||||||
close(l)
|
close(l)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
var scan_dir func(string, int)
|
|
||||||
seen_dirs := make(map[string]bool)
|
seen_dirs := make(map[string]bool)
|
||||||
scan_dir = func(dir string, level int) {
|
dir := fss.root_dir
|
||||||
if !fss.keep_going.Load() || seen_dirs[dir] {
|
pos := 0
|
||||||
return
|
// do a breadth first traversal of the filesystem
|
||||||
|
for dir != "" {
|
||||||
|
if !fss.keep_going.Load() {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
seen_dirs[dir] = true
|
if !seen_dirs[dir] {
|
||||||
entries, err := fss.dir_reader(dir, level)
|
seen_dirs[dir] = true
|
||||||
if err != nil {
|
entries, err := fss.dir_reader(dir)
|
||||||
if level == 0 {
|
if err != nil {
|
||||||
fss.keep_going.Store(false)
|
if dir == fss.root_dir {
|
||||||
fss.mutex.Lock()
|
fss.keep_going.Store(false)
|
||||||
fss.err = err
|
fss.mutex.Lock()
|
||||||
fss.mutex.Unlock()
|
fss.err = err
|
||||||
|
fss.mutex.Unlock()
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
return
|
ns := fss.results
|
||||||
}
|
new_sz := len(ns) + len(entries)
|
||||||
ns := fss.results
|
if cap(ns) < new_sz {
|
||||||
new_sz := len(ns) + len(entries)
|
ns = make([]ResultItem, len(ns), max(16*1024, new_sz, cap(ns)*2))
|
||||||
if cap(ns) < new_sz {
|
copy(ns, fss.results)
|
||||||
ns = make([]ResultItem, len(ns), max(16*1024, new_sz, cap(ns)*2))
|
}
|
||||||
copy(ns, fss.results)
|
new_items := ns[len(ns):new_sz]
|
||||||
}
|
for i, x := range entries {
|
||||||
new_items := ns[len(ns):new_sz]
|
ftype := x.Type()
|
||||||
for i, x := range entries {
|
if ftype&fs.ModeSymlink != 0 {
|
||||||
ftype := x.Type()
|
if st, err := x.Info(); err == nil && st.IsDir() {
|
||||||
if ftype&fs.ModeSymlink != 0 {
|
ftype = fs.ModeDir
|
||||||
if st, err := x.Info(); err == nil && st.IsDir() {
|
}
|
||||||
ftype = fs.ModeDir
|
}
|
||||||
|
new_items[i].ftype = ftype
|
||||||
|
new_items[i].abspath = filepath.Join(dir, x.Name())
|
||||||
|
new_items[i].text = strings.ToLower(x.Name())
|
||||||
|
}
|
||||||
|
slices.SortFunc(new_items, func(a, b ResultItem) int {
|
||||||
|
if a.ftype&fs.ModeDir == b.ftype&fs.ModeDir {
|
||||||
|
return cmp.Compare(a.text, b.text)
|
||||||
|
}
|
||||||
|
if a.ftype.IsDir() {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
})
|
||||||
|
ns = ns[0:new_sz]
|
||||||
|
fss.mutex.Lock()
|
||||||
|
fss.results = ns
|
||||||
|
listeners := fss.listeners
|
||||||
|
num := len(fss.results)
|
||||||
|
fss.mutex.Unlock()
|
||||||
|
for _, l := range listeners {
|
||||||
|
select {
|
||||||
|
case l <- num:
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_items[i].ftype = ftype
|
|
||||||
new_items[i].abspath = filepath.Join(dir, x.Name())
|
|
||||||
new_items[i].text = strings.ToLower(x.Name())
|
|
||||||
}
|
}
|
||||||
slices.SortFunc(new_items, func(a, b ResultItem) int {
|
dir = ""
|
||||||
if a.ftype&fs.ModeDir == b.ftype&fs.ModeDir {
|
for pos < len(fss.results) && dir == "" {
|
||||||
return cmp.Compare(a.text, b.text)
|
if fss.results[pos].ftype.IsDir() {
|
||||||
}
|
dir = fss.results[pos].abspath
|
||||||
if a.ftype.IsDir() {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
return 1
|
|
||||||
})
|
|
||||||
ns = ns[0:new_sz]
|
|
||||||
fss.mutex.Lock()
|
|
||||||
fss.results = ns
|
|
||||||
listeners := fss.listeners
|
|
||||||
num := len(fss.results)
|
|
||||||
fss.mutex.Unlock()
|
|
||||||
for _, l := range listeners {
|
|
||||||
select {
|
|
||||||
case l <- num:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, x := range new_items {
|
|
||||||
if x.ftype.IsDir() {
|
|
||||||
scan_dir(x.abspath, level+1)
|
|
||||||
}
|
}
|
||||||
|
pos++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scan_dir(fss.root_dir, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileSystemScorer struct {
|
type FileSystemScorer struct {
|
||||||
@@ -271,7 +274,7 @@ func (fss *FileSystemScorer) worker(on_results chan int, worker_wait *sync.WaitG
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if fss.keep_going.Load() {
|
if fss.keep_going.Load() {
|
||||||
fss.on_results(nil, true)
|
fss.on_results(fss.scanner.Error(), true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|||||||
Reference in New Issue
Block a user