ls: use numeric based enum for SortMode

This commit is contained in:
Michael Eischer 2025-02-03 21:52:57 +01:00
parent 060a44202f
commit 36d8916354
2 changed files with 46 additions and 27 deletions

View File

@ -66,7 +66,7 @@ type LsOptions struct {
Recursive bool Recursive bool
HumanReadable bool HumanReadable bool
Ncdu bool Ncdu bool
Sort string Sort SortMode
Reverse bool Reverse bool
} }
@ -81,7 +81,7 @@ func init() {
flags.BoolVar(&lsOptions.Recursive, "recursive", false, "include files in subfolders of the listed directories") flags.BoolVar(&lsOptions.Recursive, "recursive", false, "include files in subfolders of the listed directories")
flags.BoolVar(&lsOptions.HumanReadable, "human-readable", false, "print sizes in human readable format") flags.BoolVar(&lsOptions.HumanReadable, "human-readable", false, "print sizes in human readable format")
flags.BoolVar(&lsOptions.Ncdu, "ncdu", false, "output NCDU export format (pipe into 'ncdu -f -')") flags.BoolVar(&lsOptions.Ncdu, "ncdu", false, "output NCDU export format (pipe into 'ncdu -f -')")
flags.StringVarP(&lsOptions.Sort, "sort", "s", "name", "sort output by (name|size|time=mtime|atime|ctime|extension)") flags.VarP(&lsOptions.Sort, "sort", "s", "sort output by (name|size|time=mtime|atime|ctime|extension)")
flags.BoolVar(&lsOptions.Reverse, "reverse", false, "reverse sorted output") flags.BoolVar(&lsOptions.Reverse, "reverse", false, "reverse sorted output")
} }
@ -301,19 +301,13 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
if opts.Ncdu && gopts.JSON { if opts.Ncdu && gopts.JSON {
return errors.Fatal("only either '--json' or '--ncdu' can be specified") return errors.Fatal("only either '--json' or '--ncdu' can be specified")
} }
if opts.Sort != "name" && opts.Ncdu { if opts.Sort != SortModeName && opts.Ncdu {
return errors.Fatal("--sort and --ncdu are mutually exclusive") return errors.Fatal("--sort and --ncdu are mutually exclusive")
} }
if opts.Reverse && opts.Ncdu { if opts.Reverse && opts.Ncdu {
return errors.Fatal("--reverse and --ncdu are mutually exclusive") return errors.Fatal("--reverse and --ncdu are mutually exclusive")
} }
sortMode := SortModeName
err := sortMode.Set(opts.Sort)
if err != nil {
return err
}
// extract any specific directories to walk // extract any specific directories to walk
var dirs []string var dirs []string
if len(args) > 1 { if len(args) > 1 {
@ -377,7 +371,7 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
var printer lsPrinter var printer lsPrinter
collector := []toSortOutput{} collector := []toSortOutput{}
outputSort := sortMode != SortModeName || opts.Reverse outputSort := opts.Sort != SortModeName || opts.Reverse
if gopts.JSON { if gopts.JSON {
printer = &jsonLsPrinter{ printer = &jsonLsPrinter{
@ -481,13 +475,13 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri
} }
if outputSort { if outputSort {
printSortedOutput(printer, opts, sortMode, collector) printSortedOutput(printer, opts.Sort, opts.Reverse, collector)
} }
return printer.Close() return printer.Close()
} }
func printSortedOutput(printer lsPrinter, opts LsOptions, sortMode SortMode, collector []toSortOutput) { func printSortedOutput(printer lsPrinter, sortMode SortMode, reverse bool, collector []toSortOutput) {
switch sortMode { switch sortMode {
case SortModeName: case SortModeName:
case SortModeSize: case SortModeSize:
@ -534,7 +528,7 @@ func printSortedOutput(printer lsPrinter, opts LsOptions, sortMode SortMode, col
}) })
} }
if opts.Reverse { if reverse {
slices.Reverse(collector) slices.Reverse(collector)
} }
for _, elem := range collector { for _, elem := range collector {
@ -543,17 +537,17 @@ func printSortedOutput(printer lsPrinter, opts LsOptions, sortMode SortMode, col
} }
// SortMode defines the allowed sorting modes // SortMode defines the allowed sorting modes
type SortMode string type SortMode uint
// Allowed sort modes // Allowed sort modes
const ( const (
SortModeName SortMode = "name" SortModeName SortMode = iota
SortModeSize SortMode = "size" SortModeSize
SortModeAtime SortMode = "atime" SortModeAtime
SortModeCtime SortMode = "ctime" SortModeCtime
SortModeMtime SortMode = "mtime" SortModeMtime
SortModeExt SortMode = "extension" SortModeExt
SortModeInvalid SortMode = "--invalid--" SortModeInvalid
) )
// Set implements the method needed for pflag command flag parsing. // Set implements the method needed for pflag command flag parsing.
@ -573,8 +567,31 @@ func (c *SortMode) Set(s string) error {
*c = SortModeExt *c = SortModeExt
default: default:
*c = SortModeInvalid *c = SortModeInvalid
return fmt.Errorf("invalid sort mode %q, must be one of (name|size|atime|ctime|mtime=time|extension)", s) return fmt.Errorf("invalid sort mode %q, must be one of (name|size|time=mtime|atime|ctime|extension)", s)
} }
return nil return nil
} }
func (c *SortMode) String() string {
switch *c {
case SortModeName:
return "name"
case SortModeSize:
return "size"
case SortModeAtime:
return "atime"
case SortModeCtime:
return "ctime"
case SortModeMtime:
return "mtime"
case SortModeExt:
return "extension"
default:
return "invalid"
}
}
func (c *SortMode) Type() string {
return "mode"
}

View File

@ -19,7 +19,7 @@ func testRunLsWithOpts(t testing.TB, gopts GlobalOptions, opts LsOptions, args [
} }
func testRunLs(t testing.TB, gopts GlobalOptions, snapshotID string) []string { func testRunLs(t testing.TB, gopts GlobalOptions, snapshotID string) []string {
out := testRunLsWithOpts(t, gopts, LsOptions{Sort: "name"}, []string{snapshotID}) out := testRunLsWithOpts(t, gopts, LsOptions{}, []string{snapshotID})
return strings.Split(string(out), "\n") return strings.Split(string(out), "\n")
} }
@ -45,7 +45,7 @@ func TestRunLsNcdu(t *testing.T) {
{"latest", "/0"}, {"latest", "/0"},
{"latest", "/0", "/0/9"}, {"latest", "/0", "/0/9"},
} { } {
ncdu := testRunLsWithOpts(t, env.gopts, LsOptions{Ncdu: true, Sort: "name"}, paths) ncdu := testRunLsWithOpts(t, env.gopts, LsOptions{Ncdu: true}, paths)
assertIsValidJSON(t, ncdu) assertIsValidJSON(t, ncdu)
} }
} }
@ -83,7 +83,7 @@ func TestRunLsSort(t *testing.T) {
testRunBackup(t, env.testdata+"/0", []string{"for_cmd_ls"}, opts, env.gopts) testRunBackup(t, env.testdata+"/0", []string{"for_cmd_ls"}, opts, env.gopts)
// sort by size // sort by size
out := testRunLsWithOpts(t, env.gopts, LsOptions{Sort: "size"}, []string{"latest"}) out := testRunLsWithOpts(t, env.gopts, LsOptions{Sort: SortModeSize}, []string{"latest"})
fileList := strings.Split(string(out), "\n") fileList := strings.Split(string(out), "\n")
rtest.Assert(t, len(fileList) == 5, "invalid ls --sort size, expected 5 array elements, got %v", len(fileList)) rtest.Assert(t, len(fileList) == 5, "invalid ls --sort size, expected 5 array elements, got %v", len(fileList))
for i, item := range compareSize { for i, item := range compareSize {
@ -91,7 +91,7 @@ func TestRunLsSort(t *testing.T) {
} }
// sort by file extension // sort by file extension
out = testRunLsWithOpts(t, env.gopts, LsOptions{Sort: "extension"}, []string{"latest"}) out = testRunLsWithOpts(t, env.gopts, LsOptions{Sort: SortModeExt}, []string{"latest"})
fileList = strings.Split(string(out), "\n") fileList = strings.Split(string(out), "\n")
rtest.Assert(t, len(fileList) == 5, "invalid ls --sort extension, expected 5 array elements, got %v", len(fileList)) rtest.Assert(t, len(fileList) == 5, "invalid ls --sort extension, expected 5 array elements, got %v", len(fileList))
for i, item := range compareExt { for i, item := range compareExt {
@ -99,10 +99,12 @@ func TestRunLsSort(t *testing.T) {
} }
// explicit name sort // explicit name sort
out = testRunLsWithOpts(t, env.gopts, LsOptions{Sort: "name"}, []string{"latest"}) out = testRunLsWithOpts(t, env.gopts, LsOptions{Sort: SortModeName}, []string{"latest"})
fileList = strings.Split(string(out), "\n") fileList = strings.Split(string(out), "\n")
rtest.Assert(t, len(fileList) == 5, "invalid ls --sort name, expected 5 array elements, got %v", len(fileList)) rtest.Assert(t, len(fileList) == 5, "invalid ls --sort name, expected 5 array elements, got %v", len(fileList))
for i, item := range compareName { for i, item := range compareName {
rtest.Assert(t, item == fileList[i], "invalid ls --sort name, expected element '%s', got '%s'", item, fileList[i]) rtest.Assert(t, item == fileList[i], "invalid ls --sort name, expected element '%s', got '%s'", item, fileList[i])
} }
rtest.Equals(t, SortMode(0), SortModeName, "unexpected default sort mode")
} }