From 36d8916354f7e0bf10aeb4639246cbb8e392a89b Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Mon, 3 Feb 2025 21:52:57 +0100 Subject: [PATCH] ls: use numeric based enum for SortMode --- cmd/restic/cmd_ls.go | 61 +++++++++++++++++---------- cmd/restic/cmd_ls_integration_test.go | 12 +++--- 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/cmd/restic/cmd_ls.go b/cmd/restic/cmd_ls.go index 6e0d230b1..d12dd3a31 100644 --- a/cmd/restic/cmd_ls.go +++ b/cmd/restic/cmd_ls.go @@ -66,7 +66,7 @@ type LsOptions struct { Recursive bool HumanReadable bool Ncdu bool - Sort string + Sort SortMode 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.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.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") } @@ -301,19 +301,13 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri if opts.Ncdu && gopts.JSON { 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") } if opts.Reverse && opts.Ncdu { 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 var dirs []string if len(args) > 1 { @@ -377,7 +371,7 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri var printer lsPrinter collector := []toSortOutput{} - outputSort := sortMode != SortModeName || opts.Reverse + outputSort := opts.Sort != SortModeName || opts.Reverse if gopts.JSON { printer = &jsonLsPrinter{ @@ -481,13 +475,13 @@ func runLs(ctx context.Context, opts LsOptions, gopts GlobalOptions, args []stri } if outputSort { - printSortedOutput(printer, opts, sortMode, collector) + printSortedOutput(printer, opts.Sort, opts.Reverse, collector) } 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 { case SortModeName: case SortModeSize: @@ -534,7 +528,7 @@ func printSortedOutput(printer lsPrinter, opts LsOptions, sortMode SortMode, col }) } - if opts.Reverse { + if reverse { slices.Reverse(collector) } for _, elem := range collector { @@ -543,17 +537,17 @@ func printSortedOutput(printer lsPrinter, opts LsOptions, sortMode SortMode, col } // SortMode defines the allowed sorting modes -type SortMode string +type SortMode uint // Allowed sort modes const ( - SortModeName SortMode = "name" - SortModeSize SortMode = "size" - SortModeAtime SortMode = "atime" - SortModeCtime SortMode = "ctime" - SortModeMtime SortMode = "mtime" - SortModeExt SortMode = "extension" - SortModeInvalid SortMode = "--invalid--" + SortModeName SortMode = iota + SortModeSize + SortModeAtime + SortModeCtime + SortModeMtime + SortModeExt + SortModeInvalid ) // Set implements the method needed for pflag command flag parsing. @@ -573,8 +567,31 @@ func (c *SortMode) Set(s string) error { *c = SortModeExt default: *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 } + +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" +} diff --git a/cmd/restic/cmd_ls_integration_test.go b/cmd/restic/cmd_ls_integration_test.go index 29e153419..4675814b3 100644 --- a/cmd/restic/cmd_ls_integration_test.go +++ b/cmd/restic/cmd_ls_integration_test.go @@ -19,7 +19,7 @@ func testRunLsWithOpts(t testing.TB, gopts GlobalOptions, opts LsOptions, args [ } 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") } @@ -45,7 +45,7 @@ func TestRunLsNcdu(t *testing.T) { {"latest", "/0"}, {"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) } } @@ -83,7 +83,7 @@ func TestRunLsSort(t *testing.T) { testRunBackup(t, env.testdata+"/0", []string{"for_cmd_ls"}, opts, env.gopts) // 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") rtest.Assert(t, len(fileList) == 5, "invalid ls --sort size, expected 5 array elements, got %v", len(fileList)) for i, item := range compareSize { @@ -91,7 +91,7 @@ func TestRunLsSort(t *testing.T) { } // 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") rtest.Assert(t, len(fileList) == 5, "invalid ls --sort extension, expected 5 array elements, got %v", len(fileList)) for i, item := range compareExt { @@ -99,10 +99,12 @@ func TestRunLsSort(t *testing.T) { } // 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") rtest.Assert(t, len(fileList) == 5, "invalid ls --sort name, expected 5 array elements, got %v", len(fileList)) for i, item := range compareName { 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") }