Fix every finding surfaced by the canonical .golangci.yml with golangci-lint v2.12.2 (refs #61), behavior-preserving throughout: - err113: dynamic errors replaced with package-level sentinels and %w wrapping; direct comparisons converted to errors.Is - goprintffuncname: printf-style helpers renamed with an f suffix (ui.Writer message methods, cli.ReportErrorf, database.Fatalf, vaultik stdoutf) and all call sites updated - revive: stuttering type names renamed (blob.Handler, blob.WithReader, blob.ChunkPosition, storage.URL, storage.Info), doc comments added, unused parameters blanked, package comments added - contextcheck/noctx: ctx threaded through blob.Packer (AddChunk/Flush/FinalizeBlob/PackChunks) and scanner call sites; context-aware exec and sql variants used - funlen/cyclop/gocognit/nestif/dupl: oversized or duplicated functions split into focused helpers across production and test code - paralleltest/tparallel/thelper/usetesting/testpackage: tests parallelized where safe (global log.Initialize kept in the serial phase), helpers marked, t.TempDir adopted, external test packages where only exported API is used - gosec: integer conversions clamped or justified, header timeouts added, remaining findings suppressed with per-site justifications - mnd/goconst/lll/wsl_v5/nlreturn/noinlineerr/errcheck and other mechanical findings fixed directly Remove the deprecated log.LogOptions alias (callers migrated to log.Options). make check is green.
118 lines
2.9 KiB
Go
118 lines
2.9 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/spf13/cobra"
|
|
"sneak.berlin/go/vaultik/internal/config"
|
|
"sneak.berlin/go/vaultik/internal/log"
|
|
)
|
|
|
|
// NewDatabaseCommand creates the database command group
|
|
func NewDatabaseCommand() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "database",
|
|
Short: "Manage the local state database",
|
|
Long: `Commands for managing the local SQLite state database.`,
|
|
}
|
|
|
|
cmd.AddCommand(
|
|
newDatabaseDeleteCommand(),
|
|
)
|
|
|
|
return cmd
|
|
}
|
|
|
|
// newDatabaseDeleteCommand creates the database delete command.
|
|
// (Renamed from "purge"; the operation removes the SQLite file
|
|
// entirely, which is a delete, not a purge of content.)
|
|
func newDatabaseDeleteCommand() *cobra.Command {
|
|
var force bool
|
|
|
|
cmd := &cobra.Command{
|
|
Use: "delete",
|
|
Short: "Delete the local state database file",
|
|
Long: `Completely removes the local SQLite state database.
|
|
|
|
This will erase all local tracking of:
|
|
- File metadata and change detection state
|
|
- Chunk and blob mappings
|
|
- Local snapshot records
|
|
- The storage-binding record
|
|
|
|
The remote storage is NOT affected. After deletion, the next backup
|
|
will perform a full scan and re-deduplicate against existing remote
|
|
blobs, and the local index will re-bind to the currently configured
|
|
storage destination on that run.
|
|
|
|
Use --force to skip the confirmation prompt.`,
|
|
Args: cobra.NoArgs,
|
|
RunE: func(_ *cobra.Command, _ []string) error {
|
|
// Resolve config path
|
|
configPath, err := ResolveConfigPath()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Load config to get database path
|
|
cfg, err := config.Load(configPath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load config: %w", err)
|
|
}
|
|
|
|
dbPath := cfg.IndexPath
|
|
|
|
// Check if database exists
|
|
_, err = os.Stat(dbPath)
|
|
if os.IsNotExist(err) {
|
|
_, _ = fmt.Fprintf(os.Stdout, "Database does not exist: %s\n", dbPath)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Confirm unless --force
|
|
if !force {
|
|
_, _ = fmt.Fprintf(os.Stdout,
|
|
"This will delete the local state database at:\n %s\n\n", dbPath)
|
|
_, _ = fmt.Fprint(os.Stdout, "Are you sure? Type 'yes' to confirm: ")
|
|
|
|
var confirm string
|
|
|
|
_, err = fmt.Scanln(&confirm)
|
|
if err != nil || confirm != "yes" {
|
|
_, _ = fmt.Fprintln(os.Stdout, "Aborted.")
|
|
|
|
//nolint:nilerr // a failed/aborted confirmation is a clean abort
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// Delete the database file
|
|
err = os.Remove(dbPath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete database: %w", err)
|
|
}
|
|
|
|
// Also delete WAL and SHM files if they exist
|
|
walPath := dbPath + "-wal"
|
|
shmPath := dbPath + "-shm"
|
|
_ = os.Remove(walPath) // Ignore errors - files may not exist
|
|
_ = os.Remove(shmPath)
|
|
|
|
rootFlags := GetRootFlags()
|
|
if !rootFlags.Quiet {
|
|
_, _ = fmt.Fprintf(os.Stdout, "Database deleted: %s\n", dbPath)
|
|
}
|
|
|
|
log.Info("Local state database deleted", "path", dbPath)
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
cmd.Flags().BoolVar(&force, "force", false, "Skip confirmation prompt")
|
|
|
|
return cmd
|
|
}
|