ls: refactor sorting into sortedPrinter struct

This commit is contained in:
Michael Eischer 2025-02-03 22:05:40 +01:00
parent 993eb112cd
commit 1807627dda
1 changed files with 44 additions and 27 deletions

View File

@ -370,8 +370,6 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
} }
var printer lsPrinter var printer lsPrinter
collector := []toSortOutput{}
outputSort := opts.Sort != SortModeName || opts.Reverse
if gopts.JSON { if gopts.JSON {
printer = &jsonLsPrinter{ printer = &jsonLsPrinter{
@ -381,7 +379,6 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
printer = &ncduLsPrinter{ printer = &ncduLsPrinter{
out: globalOptions.stdout, out: globalOptions.stdout,
} }
outputSort = false
} else { } else {
printer = &textLsPrinter{ printer = &textLsPrinter{
dirs: dirs, dirs: dirs,
@ -389,6 +386,13 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
HumanReadable: opts.HumanReadable, HumanReadable: opts.HumanReadable,
} }
} }
if opts.Sort != SortModeName || opts.Reverse {
printer = &sortedPrinter{
printer: printer,
sortMode: opts.Sort,
reverse: opts.Reverse,
}
}
sn, subfolder, err := (&restic.SnapshotFilter{ sn, subfolder, err := (&restic.SnapshotFilter{
Hosts: opts.Hosts, Hosts: opts.Hosts,
@ -419,13 +423,9 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
printedDir := false printedDir := false
if withinDir(nodepath) { if withinDir(nodepath) {
// if we're within a target path, print the node // if we're within a target path, print the node
if outputSort {
collector = append(collector, toSortOutput{nodepath, node})
} else {
if err := printer.Node(nodepath, node, false); err != nil { if err := printer.Node(nodepath, node, false); err != nil {
return err return err
} }
}
printedDir = true printedDir = true
// if recursive listing is requested, signal the walker that it // if recursive listing is requested, signal the walker that it
@ -439,7 +439,7 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
// there yet), signal the walker to descend into any subdirs // there yet), signal the walker to descend into any subdirs
if approachingMatchingTree(nodepath) { if approachingMatchingTree(nodepath) {
// print node leading up to the target paths // print node leading up to the target paths
if !printedDir && !outputSort { if !printedDir {
return printer.Node(nodepath, node, true) return printer.Node(nodepath, node, true)
} }
return nil return nil
@ -474,39 +474,55 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
return err return err
} }
if outputSort {
printSortedOutput(printer, opts.Sort, opts.Reverse, collector)
}
return printer.Close() return printer.Close()
} }
func printSortedOutput(printer lsPrinter, sortMode SortMode, reverse bool, collector []toSortOutput) { type sortedPrinter struct {
switch sortMode { printer lsPrinter
collector []toSortOutput
sortMode SortMode
reverse bool
}
func (p *sortedPrinter) Snapshot(sn *restic.Snapshot) error {
return p.printer.Snapshot(sn)
}
func (p *sortedPrinter) Node(path string, node *restic.Node, isPrefixDirectory bool) error {
if !isPrefixDirectory {
p.collector = append(p.collector, toSortOutput{path, node})
}
return nil
}
func (p *sortedPrinter) LeaveDir(_ string) error {
return nil
}
func (p *sortedPrinter) Close() error {
switch p.sortMode {
case SortModeName: case SortModeName:
case SortModeSize: case SortModeSize:
slices.SortStableFunc(collector, func(a, b toSortOutput) int { slices.SortStableFunc(p.collector, func(a, b toSortOutput) int {
return cmp.Or( return cmp.Or(
cmp.Compare(a.node.Size, b.node.Size), cmp.Compare(a.node.Size, b.node.Size),
cmp.Compare(a.nodepath, b.nodepath), cmp.Compare(a.nodepath, b.nodepath),
) )
}) })
case SortModeMtime: case SortModeMtime:
slices.SortStableFunc(collector, func(a, b toSortOutput) int { slices.SortStableFunc(p.collector, func(a, b toSortOutput) int {
return cmp.Or( return cmp.Or(
a.node.ModTime.Compare(b.node.ModTime), a.node.ModTime.Compare(b.node.ModTime),
cmp.Compare(a.nodepath, b.nodepath), cmp.Compare(a.nodepath, b.nodepath),
) )
}) })
case SortModeAtime: case SortModeAtime:
slices.SortStableFunc(collector, func(a, b toSortOutput) int { slices.SortStableFunc(p.collector, func(a, b toSortOutput) int {
return cmp.Or( return cmp.Or(
a.node.AccessTime.Compare(b.node.AccessTime), a.node.AccessTime.Compare(b.node.AccessTime),
cmp.Compare(a.nodepath, b.nodepath), cmp.Compare(a.nodepath, b.nodepath),
) )
}) })
case SortModeCtime: case SortModeCtime:
slices.SortStableFunc(collector, func(a, b toSortOutput) int { slices.SortStableFunc(p.collector, func(a, b toSortOutput) int {
return cmp.Or( return cmp.Or(
a.node.ChangeTime.Compare(b.node.ChangeTime), a.node.ChangeTime.Compare(b.node.ChangeTime),
cmp.Compare(a.nodepath, b.nodepath), cmp.Compare(a.nodepath, b.nodepath),
@ -514,13 +530,13 @@ func printSortedOutput(printer lsPrinter, sortMode SortMode, reverse bool, colle
}) })
case SortModeExt: case SortModeExt:
// map name to extension // map name to extension
mapExt := make(map[string]string, len(collector)) mapExt := make(map[string]string, len(p.collector))
for _, item := range collector { for _, item := range p.collector {
ext := filepath.Ext(item.nodepath) ext := filepath.Ext(item.nodepath)
mapExt[item.nodepath] = ext mapExt[item.nodepath] = ext
} }
slices.SortStableFunc(collector, func(a, b toSortOutput) int { slices.SortStableFunc(p.collector, func(a, b toSortOutput) int {
return cmp.Or( return cmp.Or(
cmp.Compare(mapExt[a.nodepath], mapExt[b.nodepath]), cmp.Compare(mapExt[a.nodepath], mapExt[b.nodepath]),
cmp.Compare(a.nodepath, b.nodepath), cmp.Compare(a.nodepath, b.nodepath),
@ -528,12 +544,13 @@ func printSortedOutput(printer lsPrinter, sortMode SortMode, reverse bool, colle
}) })
} }
if reverse { if p.reverse {
slices.Reverse(collector) slices.Reverse(p.collector)
} }
for _, elem := range collector { for _, elem := range p.collector {
_ = printer.Node(elem.nodepath, elem.node, false) _ = p.printer.Node(elem.nodepath, elem.node, false)
} }
return nil
} }
// SortMode defines the allowed sorting modes // SortMode defines the allowed sorting modes