diff --git a/cmd/stbak/cmd/drive_eject.go b/cmd/stbak/cmd/drive_eject.go index b4f9c1a..fe6d09a 100644 --- a/cmd/stbak/cmd/drive_eject.go +++ b/cmd/stbak/cmd/drive_eject.go @@ -9,7 +9,7 @@ import ( "github.com/volatiletech/sqlboiler/v4/boil" ) -var ejectCmd = &cobra.Command{ +var driveEjectCmd = &cobra.Command{ Use: "eject", Aliases: []string{"e"}, Short: "Eject the tape (tape only)", @@ -35,5 +35,5 @@ var ejectCmd = &cobra.Command{ func init() { viper.AutomaticEnv() - driveCmd.AddCommand(ejectCmd) + driveCmd.AddCommand(driveEjectCmd) } diff --git a/cmd/stbak/cmd/drive_tell.go b/cmd/stbak/cmd/drive_tell.go index 173eeb8..9bc231d 100644 --- a/cmd/stbak/cmd/drive_tell.go +++ b/cmd/stbak/cmd/drive_tell.go @@ -10,7 +10,7 @@ import ( "github.com/volatiletech/sqlboiler/v4/boil" ) -var tellCmd = &cobra.Command{ +var driveTellCmd = &cobra.Command{ Use: "tell", Aliases: []string{"t"}, Short: "Get the current record (tape only)", @@ -43,5 +43,5 @@ var tellCmd = &cobra.Command{ func init() { viper.AutomaticEnv() - driveCmd.AddCommand(tellCmd) + driveCmd.AddCommand(driveTellCmd) } diff --git a/cmd/stbak/cmd/query.go b/cmd/stbak/cmd/list.go similarity index 82% rename from cmd/stbak/cmd/query.go rename to cmd/stbak/cmd/list.go index 700f29c..4439911 100644 --- a/cmd/stbak/cmd/query.go +++ b/cmd/stbak/cmd/list.go @@ -11,10 +11,10 @@ import ( "github.com/volatiletech/sqlboiler/v4/boil" ) -var queryCmd = &cobra.Command{ - Use: "query", - Aliases: []string{"q"}, - Short: "Query the contents of an index", +var listCmd = &cobra.Command{ + Use: "list", + Aliases: []string{"l"}, + Short: "List the contents of a directory in the index", RunE: func(cmd *cobra.Command, args []string) error { if err := viper.BindPFlags(cmd.PersistentFlags()); err != nil { return err @@ -56,9 +56,9 @@ var queryCmd = &cobra.Command{ } func init() { - queryCmd.PersistentFlags().StringP(nameFlag, "n", "", "Name of the file or directory to query") + listCmd.PersistentFlags().StringP(nameFlag, "n", "", "Directory to list the contents of") viper.AutomaticEnv() - rootCmd.AddCommand(queryCmd) + rootCmd.AddCommand(listCmd) } diff --git a/cmd/stbak/cmd/recovery_index.go b/cmd/stbak/cmd/recovery_index.go index 906d455..4d1bdef 100644 --- a/cmd/stbak/cmd/recovery_index.go +++ b/cmd/stbak/cmd/recovery_index.go @@ -20,7 +20,7 @@ import ( "github.com/volatiletech/sqlboiler/v4/boil" ) -var indexCmd = &cobra.Command{ +var recoveryIndexCmd = &cobra.Command{ Use: "index", Aliases: []string{"i"}, Short: "Index contents of tape or tar file", @@ -216,14 +216,14 @@ func index( } func init() { - indexCmd.PersistentFlags().IntP(recordSizeFlag, "e", 20, "Amount of 512-bit blocks per record") - indexCmd.PersistentFlags().IntP(recordFlag, "r", 0, "Record to seek too before counting") - indexCmd.PersistentFlags().IntP(blockFlag, "b", 0, "Block in record to seek too before counting") - indexCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Remove the old index before starting to index") + recoveryIndexCmd.PersistentFlags().IntP(recordSizeFlag, "e", 20, "Amount of 512-bit blocks per record") + recoveryIndexCmd.PersistentFlags().IntP(recordFlag, "r", 0, "Record to seek too before counting") + recoveryIndexCmd.PersistentFlags().IntP(blockFlag, "b", 0, "Block in record to seek too before counting") + recoveryIndexCmd.PersistentFlags().BoolP(overwriteFlag, "o", false, "Remove the old index before starting to index") viper.AutomaticEnv() - recoveryCmd.AddCommand(indexCmd) + recoveryCmd.AddCommand(recoveryIndexCmd) } func indexHeader(record, block int64, hdr *tar.Header, metadataPersister *persisters.MetadataPersister) error { diff --git a/cmd/stbak/cmd/recovery_list.go b/cmd/stbak/cmd/recovery_list.go index 52264bf..3ba090a 100644 --- a/cmd/stbak/cmd/recovery_list.go +++ b/cmd/stbak/cmd/recovery_list.go @@ -14,7 +14,7 @@ import ( "github.com/volatiletech/sqlboiler/v4/boil" ) -var listCmd = &cobra.Command{ +var recoveryListCmd = &cobra.Command{ Use: "list", Aliases: []string{"l"}, Short: "List contents of tape or tar file", @@ -184,11 +184,11 @@ var listCmd = &cobra.Command{ } func init() { - listCmd.PersistentFlags().IntP(recordSizeFlag, "e", 20, "Amount of 512-bit blocks per record") - listCmd.PersistentFlags().IntP(recordFlag, "r", 0, "Record to seek too before counting") - listCmd.PersistentFlags().IntP(blockFlag, "b", 0, "Block in record to seek too before counting") + recoveryListCmd.PersistentFlags().IntP(recordSizeFlag, "e", 20, "Amount of 512-bit blocks per record") + recoveryListCmd.PersistentFlags().IntP(recordFlag, "r", 0, "Record to seek too before counting") + recoveryListCmd.PersistentFlags().IntP(blockFlag, "b", 0, "Block in record to seek too before counting") viper.AutomaticEnv() - recoveryCmd.AddCommand(listCmd) + recoveryCmd.AddCommand(recoveryListCmd) } diff --git a/cmd/stbak/cmd/recovery_restore.go b/cmd/stbak/cmd/recovery_restore.go index 7f4c7fc..813066e 100644 --- a/cmd/stbak/cmd/recovery_restore.go +++ b/cmd/stbak/cmd/recovery_restore.go @@ -21,7 +21,7 @@ const ( previewFlag = "preview" ) -var restoreCmd = &cobra.Command{ +var recoveryRestoreCmd = &cobra.Command{ Use: "restore", Aliases: []string{"r"}, Short: "Restore a file", @@ -105,13 +105,13 @@ var restoreCmd = &cobra.Command{ } func init() { - restoreCmd.PersistentFlags().IntP(recordSizeFlag, "e", 20, "Amount of 512-bit blocks per record") - restoreCmd.PersistentFlags().IntP(recordFlag, "r", 0, "Record to seek too") - restoreCmd.PersistentFlags().IntP(blockFlag, "b", 0, "Block in record to seek too") - restoreCmd.PersistentFlags().StringP(dstFlag, "d", "", "File to restore to (archived name by default)") - restoreCmd.PersistentFlags().BoolP(previewFlag, "p", false, "Only read the header") + recoveryRestoreCmd.PersistentFlags().IntP(recordSizeFlag, "e", 20, "Amount of 512-bit blocks per record") + recoveryRestoreCmd.PersistentFlags().IntP(recordFlag, "r", 0, "Record to seek too") + recoveryRestoreCmd.PersistentFlags().IntP(blockFlag, "b", 0, "Block in record to seek too") + recoveryRestoreCmd.PersistentFlags().StringP(dstFlag, "d", "", "File to restore to (archived name by default)") + recoveryRestoreCmd.PersistentFlags().BoolP(previewFlag, "p", false, "Only read the header") viper.AutomaticEnv() - recoveryCmd.AddCommand(restoreCmd) + recoveryCmd.AddCommand(recoveryRestoreCmd) } diff --git a/pkg/persisters/metadata.go b/pkg/persisters/metadata.go index 94d51fd..8bc0553 100644 --- a/pkg/persisters/metadata.go +++ b/pkg/persisters/metadata.go @@ -114,27 +114,57 @@ func (p *MetadataPersister) GetHeaderChildren(ctx context.Context, name string) } func (p *MetadataPersister) GetHeaderDirectChildren(ctx context.Context, name string) (models.HeaderSlice, error) { - if name == "" || name == "." || name == "/" { - return p.GetHeaders(ctx) + prefix := strings.TrimSuffix(name, "/") + "/" + + // Root node + if name == "" || name == "." || name == "/" || name == "./" { + prefix = "" } - prefixWithoutTrailingSlash := strings.TrimSuffix(name, "/") - prefixWithTrailingSlash := prefixWithoutTrailingSlash + "/%" - headers := models.HeaderSlice{} + if err := queries.Raw( fmt.Sprintf( - `select * from %v where %v = ? or %v = ? or (%v like ? and %v not like ?)`, + `select %v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v, %v, + length(replace(%v, ?, '')) - length(replace(replace(%v, ?, ''), '/', '')) as depth +from %v +where %v like ? + and ( + depth = 0 + or ( + %v like '%%/' + and depth = 1 + ) + ) + and not %v in ('', '.', '/', './');`, + models.HeaderColumns.Record, + models.HeaderColumns.Block, + models.HeaderColumns.Typeflag, + models.HeaderColumns.Name, + models.HeaderColumns.Linkname, + models.HeaderColumns.Size, + models.HeaderColumns.Mode, + models.HeaderColumns.UID, + models.HeaderColumns.Gid, + models.HeaderColumns.Uname, + models.HeaderColumns.Gname, + models.HeaderColumns.Modtime, + models.HeaderColumns.Accesstime, + models.HeaderColumns.Changetime, + models.HeaderColumns.Devmajor, + models.HeaderColumns.Devminor, + models.HeaderColumns.Paxrecords, + models.HeaderColumns.Format, + models.HeaderColumns.Name, + models.HeaderColumns.Name, models.TableNames.Headers, models.HeaderColumns.Name, models.HeaderColumns.Name, models.HeaderColumns.Name, - models.HeaderColumns.Name, ), - prefixWithoutTrailingSlash, - prefixWithTrailingSlash, - prefixWithTrailingSlash, - prefixWithTrailingSlash+"/%", + prefix, + prefix, + prefix+"%", ).Bind(ctx, p.db, &headers); err != nil { if err == sql.ErrNoRows { return headers, nil