From fdf0159a17a33b58d420199f2f5e5437df2e773c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20L=C3=B3pez?= <1953782+julio-lopez@users.noreply.github.com> Date: Sun, 6 Sep 2026 15:08:49 -0700 Subject: [PATCH] refactor(general): cleanup various nits (#5618) - use struct field initialization idiom - clarify error message - directly use s.rootctx in server request processing - refactor: use require in e2e ACL test - inline constant definition - modernize with `strings.Cut` - modernize with slices.Backward - simplify timeFormat initialization - refactor testing: check `Scanner.Err()` in testenv - remove spurious parenthesis - trueStr and falseStr consts - use inheritPolicyString - use const in cache info - "bytes" const in ui task counters - use common consts in gettool --- cli/app.go | 13 ++-- cli/cli_progress.go | 4 +- cli/command_blob_shards_modify_test.go | 2 +- cli/command_blob_show_test.go | 6 +- cli/command_cache_info.go | 26 ++++---- cli/command_content_verify_test.go | 2 +- cli/command_index_inspect_test.go | 2 +- cli/command_logs_test.go | 6 +- cli/command_ls.go | 2 +- cli/command_policy_set.go | 6 +- cli/command_policy_set_test.go | 38 ++++++------ cli/command_policy_show.go | 4 +- cli/command_repository_connect.go | 2 +- cli/command_repository_sync.go | 2 +- cli/command_repository_upgrade.go | 4 +- cli/command_restore.go | 14 ++--- cli/command_server_start.go | 10 ++-- cli/command_snapshot_create.go | 4 +- cli/command_snapshot_list.go | 4 +- cli/command_snapshot_migrate.go | 2 +- cli/password_darwin.go | 2 +- cli/password_linux.go | 2 +- cli/password_windows.go | 2 +- cli/storage_rclone.go | 2 +- internal/bigmap/bigmap_internal.go | 5 +- internal/logfile/logfile.go | 5 +- internal/scrubber/scrub_sensitive.go | 2 +- internal/server/server.go | 4 +- internal/uitask/uitask_counter.go | 10 ++-- repo/blob/sharded/sharded_parameters.go | 2 +- repo/buildinfo.go | 2 +- repo/buildinfo_test.go | 6 +- repo/connect.go | 8 +-- repo/content/content_manager_test.go | 2 +- repo/manifest/committed_manifest_manager.go | 2 +- repo/repository.go | 2 + snapshot/policy/policy_tree.go | 2 +- tests/end_to_end_test/acl_test.go | 22 +++---- tests/end_to_end_test/auto_update_test.go | 4 +- tests/end_to_end_test/index_recover_test.go | 2 +- tests/end_to_end_test/main_test.go | 5 ++ .../repository_set_client_test.go | 4 +- tests/end_to_end_test/server_start_test.go | 2 +- tests/end_to_end_test/snapshot_create_test.go | 2 +- tests/end_to_end_test/snapshot_fail_test.go | 16 ++--- tests/robustness/snapmeta/kopia_persister.go | 2 +- tests/testenv/cli_test_env.go | 16 ++++- tools/cli2md/cli2md.go | 2 +- tools/gettool/gettool.go | 59 +++++++++++-------- 49 files changed, 193 insertions(+), 156 deletions(-) diff --git a/cli/app.go b/cli/app.go index 4a94fdbb4..161002459 100644 --- a/cli/app.go +++ b/cli/app.go @@ -29,6 +29,11 @@ "github.com/kopia/kopia/snapshot/snapshotmaintenance" ) +const ( + falseStr = "false" + trueStr = "true" +) + var log = logging.Module("kopia/cli") var tracer = otel.Tracer("cli") @@ -266,22 +271,22 @@ func (c *App) setup(app *kingpin.Application) { return nil }).Bool() - app.Flag("auto-maintenance", "Automatic maintenance").Default("true").Hidden().BoolVar(&c.enableAutomaticMaintenance) + app.Flag("auto-maintenance", "Automatic maintenance").Default(trueStr).Hidden().BoolVar(&c.enableAutomaticMaintenance) // hidden flags to control auto-update behavior. app.Flag("initial-update-check-delay", "Initial delay before first time update check").Default("24h").Hidden().Envar(c.EnvName("KOPIA_INITIAL_UPDATE_CHECK_DELAY")).DurationVar(&c.initialUpdateCheckDelay) app.Flag("update-check-interval", "Interval between update checks").Default("168h").Hidden().Envar(c.EnvName("KOPIA_UPDATE_CHECK_INTERVAL")).DurationVar(&c.updateCheckInterval) app.Flag("update-available-notify-interval", "Interval between update notifications").Default("1h").Hidden().Envar(c.EnvName("KOPIA_UPDATE_NOTIFY_INTERVAL")).DurationVar(&c.updateAvailableNotifyInterval) app.Flag("config-file", "Specify the config file to use").Default("repository.config").Envar(c.EnvName("KOPIA_CONFIG_PATH")).StringVar(&c.configPath) - app.Flag("trace-storage", "Enables tracing of storage operations.").Default("true").Hidden().BoolVar(&c.traceStorage) + app.Flag("trace-storage", "Enables tracing of storage operations.").Default(trueStr).Hidden().BoolVar(&c.traceStorage) app.Flag("timezone", "Format time according to specified time zone (local, utc, original or time zone name)").Hidden().StringVar(&timeZone) app.Flag("password", "Repository password.").Envar(c.EnvName("KOPIA_PASSWORD")).Short('p').StringVar(&c.password) - app.Flag("persist-credentials", "Persist credentials").Default("true").Envar(c.EnvName("KOPIA_PERSIST_CREDENTIALS_ON_CONNECT")).BoolVar(&c.persistCredentials) + app.Flag("persist-credentials", "Persist credentials").Default(trueStr).Envar(c.EnvName("KOPIA_PERSIST_CREDENTIALS_ON_CONNECT")).BoolVar(&c.persistCredentials) app.Flag("disable-repository-log", "Disable repository log").Hidden().Envar(c.EnvName("KOPIA_DISABLE_REPOSITORY_LOG")).BoolVar(&c.disableRepositoryLog) app.Flag("dangerous-commands", "Enable dangerous commands that could result in data loss and repository corruption.").Hidden().Envar(c.EnvName("KOPIA_DANGEROUS_COMMANDS")).StringVar(&c.DangerousCommands) app.Flag("track-releasable", "Enable tracking of releasable resources.").Hidden().Envar(c.EnvName("KOPIA_TRACK_RELEASABLE")).StringsVar(&c.trackReleasable) app.Flag("upgrade-owner-id", "Repository format upgrade owner-id.").Hidden().Envar(c.EnvName("KOPIA_REPO_UPGRADE_OWNER_ID")).StringVar(&c.upgradeOwnerID) - app.Flag("upgrade-no-block", "Do not block when repository format upgrade is in progress, instead exit with a message.").Hidden().Default("false").Envar(c.EnvName("KOPIA_REPO_UPGRADE_NO_BLOCK")).BoolVar(&c.doNotWaitForUpgrade) + app.Flag("upgrade-no-block", "Do not block when repository format upgrade is in progress, instead exit with a message.").Hidden().Default(falseStr).Envar(c.EnvName("KOPIA_REPO_UPGRADE_NO_BLOCK")).BoolVar(&c.doNotWaitForUpgrade) app.Flag("error-notifications", "Send notification on errors").Hidden(). Envar(c.EnvName("KOPIA_SEND_ERROR_NOTIFICATIONS")). Default(errorNotificationsNonInteractive). diff --git a/cli/cli_progress.go b/cli/cli_progress.go index 02a1d5170..758184453 100644 --- a/cli/cli_progress.go +++ b/cli/cli_progress.go @@ -31,10 +31,10 @@ type progressFlags struct { } func (p *progressFlags) setup(svc appServices, app *kingpin.Application) { - progressDefault := "false" + progressDefault := falseStr if fd, err := intFd(os.Stdout); err == nil && term.IsTerminal(fd) { - progressDefault = "true" + progressDefault = trueStr } app.Flag("progress", "Enable progress output").Default(progressDefault).BoolVar(&p.enableProgress) diff --git a/cli/command_blob_shards_modify_test.go b/cli/command_blob_shards_modify_test.go index 395f403b9..eace6e07f 100644 --- a/cli/command_blob_shards_modify_test.go +++ b/cli/command_blob_shards_modify_test.go @@ -16,7 +16,7 @@ func TestBlobShardsModify(t *testing.T) { env.RunAndExpectSuccess(t, "repo", "create", "filesystem", "--path", env.RepoDir) - someQBlob := strings.Split(env.RunAndExpectSuccess(t, "blob", "list", "--prefix=q")[0], " ")[0] + someQBlob, _, _ := strings.Cut(env.RunAndExpectSuccess(t, "blob", "list", "--prefix=q")[0], " ") // verify default sharding is 1,3 require.FileExists(t, filepath.Join(env.RepoDir, someQBlob[0:1], someQBlob[1:4], someQBlob[4:]+sharded.CompleteBlobSuffix)) diff --git a/cli/command_blob_show_test.go b/cli/command_blob_show_test.go index 7d52b956c..30e5538fe 100644 --- a/cli/command_blob_show_test.go +++ b/cli/command_blob_show_test.go @@ -20,14 +20,14 @@ func (s *formatSpecificTestSuite) TestBlobShow(t *testing.T) { } } - someQBlob := strings.Split(env.RunAndExpectSuccess(t, "blob", "list", "--prefix=q")[0], " ")[0] + someQBlob, _, _ := strings.Cut(env.RunAndExpectSuccess(t, "blob", "list", "--prefix=q")[0], " ") if hasEpochManager { - someXNBlob := strings.Split(env.RunAndExpectSuccess(t, "blob", "list", "--prefix=xn")[0], " ")[0] + someXNBlob, _, _ := strings.Cut(env.RunAndExpectSuccess(t, "blob", "list", "--prefix=xn")[0], " ") env.RunAndExpectSuccess(t, "blob", "show", someXNBlob) env.RunAndExpectSuccess(t, "blob", "show", "--decrypt", someXNBlob) } else { - someNBlob := strings.Split(env.RunAndExpectSuccess(t, "blob", "list", "--prefix=n")[0], " ")[0] + someNBlob, _, _ := strings.Cut(env.RunAndExpectSuccess(t, "blob", "list", "--prefix=n")[0], " ") env.RunAndExpectSuccess(t, "blob", "show", someNBlob) env.RunAndExpectSuccess(t, "blob", "show", "--decrypt", someNBlob) } diff --git a/cli/command_cache_info.go b/cli/command_cache_info.go index d2062eebe..b9aa5833c 100644 --- a/cli/command_cache_info.go +++ b/cli/command_cache_info.go @@ -31,6 +31,12 @@ func (c *commandCacheInfo) setup(svc appServices, parent commandParent) { } func (c *commandCacheInfo) run(ctx context.Context, _ repo.Repository) error { + const ( + contents = "contents" + metadata = "metadata" + serverContents = "server-contents" + ) + opts, err := repo.GetCachingOptions(ctx, c.svc.repositoryConfigFileName()) if err != nil { return errors.Wrap(err, "error getting cache options") @@ -47,22 +53,22 @@ func (c *commandCacheInfo) run(ctx context.Context, _ repo.Repository) error { } path2SoftLimit := map[string]int64{ - "contents": opts.ContentCacheSizeBytes, - "metadata": opts.MetadataCacheSizeBytes, - "server-contents": opts.ContentCacheSizeBytes, + contents: opts.ContentCacheSizeBytes, + metadata: opts.MetadataCacheSizeBytes, + serverContents: opts.ContentCacheSizeBytes, } path2HardLimit := map[string]int64{ - "contents": opts.ContentCacheSizeLimitBytes, - "metadata": opts.MetadataCacheSizeLimitBytes, - "server-contents": opts.ContentCacheSizeLimitBytes, + contents: opts.ContentCacheSizeLimitBytes, + metadata: opts.MetadataCacheSizeLimitBytes, + serverContents: opts.ContentCacheSizeLimitBytes, } path2SweepAgeSeconds := map[string]time.Duration{ - "contents": opts.MinContentSweepAge.DurationOrDefault(content.DefaultDataCacheSweepAge), - "metadata": opts.MinMetadataSweepAge.DurationOrDefault(content.DefaultMetadataCacheSweepAge), - "indexes": opts.MinIndexSweepAge.DurationOrDefault(content.DefaultIndexCacheSweepAge), - "server-contents": opts.MinContentSweepAge.DurationOrDefault(content.DefaultDataCacheSweepAge), + contents: opts.MinContentSweepAge.DurationOrDefault(content.DefaultDataCacheSweepAge), + metadata: opts.MinMetadataSweepAge.DurationOrDefault(content.DefaultMetadataCacheSweepAge), + "indexes": opts.MinIndexSweepAge.DurationOrDefault(content.DefaultIndexCacheSweepAge), + serverContents: opts.MinContentSweepAge.DurationOrDefault(content.DefaultDataCacheSweepAge), } for _, ent := range entries { diff --git a/cli/command_content_verify_test.go b/cli/command_content_verify_test.go index a4d2ec171..b6fc90525 100644 --- a/cli/command_content_verify_test.go +++ b/cli/command_content_verify_test.go @@ -25,7 +25,7 @@ func (s *formatSpecificTestSuite) TestContentVerify(t *testing.T) { env.RunAndExpectSuccess(t, "content", "verify", "--download-percent=30") // delete one of 'p' blobs. - blobIDToDelete := strings.Split(env.RunAndExpectSuccess(t, "blob", "list", "--prefix=p")[0], " ")[0] + blobIDToDelete, _, _ := strings.Cut(env.RunAndExpectSuccess(t, "blob", "list", "--prefix=p")[0], " ") blobList := env.RunAndExpectSuccess(t, "blob", "list") t.Logf("blob list: %v", strings.Join(blobList, "\n")) env.RunAndExpectSuccess(t, "blob", "delete", blobIDToDelete) diff --git a/cli/command_index_inspect_test.go b/cli/command_index_inspect_test.go index 310d5c0ae..7047bb0cf 100644 --- a/cli/command_index_inspect_test.go +++ b/cli/command_index_inspect_test.go @@ -14,7 +14,7 @@ func (s *formatSpecificTestSuite) TestIndexInspect(t *testing.T) { env.RunAndExpectSuccess(t, "repo", "create", "filesystem", "--path", env.RepoDir) - someIndex := strings.Split(env.RunAndExpectSuccess(t, "index", "list")[0], " ")[0] + someIndex, _, _ := strings.Cut(env.RunAndExpectSuccess(t, "index", "list")[0], " ") someContentID := env.RunAndExpectSuccess(t, "content", "list")[0] env.RunAndExpectSuccess(t, "index", "inspect", someIndex) env.RunAndExpectSuccess(t, "index", "inspect", "--active") diff --git a/cli/command_logs_test.go b/cli/command_logs_test.go index f8a0fecde..a484d97cd 100644 --- a/cli/command_logs_test.go +++ b/cli/command_logs_test.go @@ -36,9 +36,9 @@ func TestLogsCommands(t *testing.T) { e.RunAndExpectSuccess(t, "snapshot", "create", testutil.TempDirectory(t)) lines := e.RunAndVerifyOutputLineCount(t, 3, "logs", "list") - firstLogID := strings.Split(lines[0], " ")[0] - secondLogID := strings.Split(lines[1], " ")[0] - thirdLogID := strings.Split(lines[2], " ")[0] + firstLogID, _, _ := strings.Cut(lines[0], " ") + secondLogID, _, _ := strings.Cut(lines[1], " ") + thirdLogID, _, _ := strings.Cut(lines[2], " ") firstLogLines := e.RunAndExpectSuccess(t, "logs", "show", firstLogID) secondLogLines := e.RunAndExpectSuccess(t, "logs", "show", secondLogID) diff --git a/cli/command_ls.go b/cli/command_ls.go index 7b830d384..533de848a 100644 --- a/cli/command_ls.go +++ b/cli/command_ls.go @@ -31,7 +31,7 @@ func (c *commandList) setup(svc appServices, parent commandParent) { cmd.Flag("human-readable", "Show human-readable sizes").Short('h').BoolVar(&c.humanReadable) cmd.Flag("recursive", "Recursive output").Short('r').BoolVar(&c.recursive) cmd.Flag("show-object-id", "Show object IDs").Short('o').BoolVar(&c.showOID) - cmd.Flag("error-summary", "Emit error summary").Default("true").BoolVar(&c.errorSummary) + cmd.Flag("error-summary", "Emit error summary").Default(trueStr).BoolVar(&c.errorSummary) cmd.Arg("object-path", "Path").Required().StringVar(&c.path) cmd.Action(svc.repositoryReaderAction(c.run)) diff --git a/cli/command_policy_set.go b/cli/command_policy_set.go index 27868ad58..90721ac2e 100644 --- a/cli/command_policy_set.go +++ b/cli/command_policy_set.go @@ -50,14 +50,14 @@ func (c *commandPolicySet) setup(svc appServices, parent commandParent) { cmd.Action(svc.repositoryWriterAction(c.run)) } -//nolint:gochecknoglobals -var booleanEnumValues = []string{"true", "false", "inherit"} - const ( inheritPolicyString = "inherit" defaultPolicyString = "default" ) +//nolint:gochecknoglobals +var booleanEnumValues = []string{trueStr, falseStr, inheritPolicyString} + func (c *commandPolicySet) run(ctx context.Context, rep repo.RepositoryWriter) error { targets, err := c.policyTargets(ctx, rep) if err != nil { diff --git a/cli/command_policy_set_test.go b/cli/command_policy_set_test.go index 04e63a147..c92c6d5e0 100644 --- a/cli/command_policy_set_test.go +++ b/cli/command_policy_set_test.go @@ -54,7 +54,7 @@ func TestSetErrorHandlingPolicyFromFlags(t *testing.T) { { name: "One is malformed, the other well formed", startingPolicy: &policy.ErrorHandlingPolicy{}, - fileArg: "true", + fileArg: trueStr, dirArg: "some-malformed-arg", expResult: &policy.ErrorHandlingPolicy{ IgnoreFileErrors: policy.NewOptionalBool(true), @@ -66,8 +66,8 @@ func TestSetErrorHandlingPolicyFromFlags(t *testing.T) { { name: "Inherit case", startingPolicy: &policy.ErrorHandlingPolicy{}, - fileArg: "inherit", - dirArg: "inherit", + fileArg: inheritPolicyString, + dirArg: inheritPolicyString, expResult: &policy.ErrorHandlingPolicy{ IgnoreFileErrors: nil, IgnoreDirectoryErrors: nil, @@ -77,8 +77,8 @@ func TestSetErrorHandlingPolicyFromFlags(t *testing.T) { { name: "Set to true", startingPolicy: &policy.ErrorHandlingPolicy{}, - fileArg: "true", - dirArg: "true", + fileArg: trueStr, + dirArg: trueStr, expResult: &policy.ErrorHandlingPolicy{ IgnoreFileErrors: policy.NewOptionalBool(true), IgnoreDirectoryErrors: policy.NewOptionalBool(true), @@ -91,8 +91,8 @@ func TestSetErrorHandlingPolicyFromFlags(t *testing.T) { IgnoreFileErrors: policy.NewOptionalBool(true), IgnoreDirectoryErrors: policy.NewOptionalBool(true), }, - fileArg: "false", - dirArg: "false", + fileArg: falseStr, + dirArg: falseStr, expResult: &policy.ErrorHandlingPolicy{ IgnoreFileErrors: policy.NewOptionalBool(false), IgnoreDirectoryErrors: policy.NewOptionalBool(false), @@ -105,8 +105,8 @@ func TestSetErrorHandlingPolicyFromFlags(t *testing.T) { IgnoreFileErrors: policy.NewOptionalBool(true), IgnoreDirectoryErrors: policy.NewOptionalBool(false), }, - fileArg: "false", - dirArg: "true", + fileArg: falseStr, + dirArg: trueStr, expResult: &policy.ErrorHandlingPolicy{ IgnoreFileErrors: policy.NewOptionalBool(false), IgnoreDirectoryErrors: policy.NewOptionalBool(true), @@ -119,8 +119,8 @@ func TestSetErrorHandlingPolicyFromFlags(t *testing.T) { IgnoreFileErrors: policy.NewOptionalBool(false), IgnoreDirectoryErrors: policy.NewOptionalBool(true), }, - fileArg: "true", - dirArg: "false", + fileArg: trueStr, + dirArg: falseStr, expResult: &policy.ErrorHandlingPolicy{ IgnoreFileErrors: policy.NewOptionalBool(true), IgnoreDirectoryErrors: policy.NewOptionalBool(false), @@ -133,8 +133,8 @@ func TestSetErrorHandlingPolicyFromFlags(t *testing.T) { IgnoreFileErrors: policy.NewOptionalBool(true), IgnoreDirectoryErrors: policy.NewOptionalBool(false), }, - fileArg: "inherit", - dirArg: "true", + fileArg: inheritPolicyString, + dirArg: trueStr, expResult: &policy.ErrorHandlingPolicy{ IgnoreFileErrors: nil, IgnoreDirectoryErrors: policy.NewOptionalBool(true), @@ -147,8 +147,8 @@ func TestSetErrorHandlingPolicyFromFlags(t *testing.T) { IgnoreFileErrors: policy.NewOptionalBool(false), IgnoreDirectoryErrors: policy.NewOptionalBool(true), }, - fileArg: "true", - dirArg: "inherit", + fileArg: trueStr, + dirArg: inheritPolicyString, expResult: &policy.ErrorHandlingPolicy{ IgnoreFileErrors: policy.NewOptionalBool(true), IgnoreDirectoryErrors: nil, @@ -354,7 +354,7 @@ func TestSetSchedulingPolicyFromFlags(t *testing.T) { startingPolicy: &policy.SchedulingPolicy{ TimesOfDay: []policy.TimeOfDay{{Hour: 12, Minute: 0}}, }, - timesOfDayArg: []string{"inherit"}, + timesOfDayArg: []string{inheritPolicyString}, expResult: &policy.SchedulingPolicy{ TimesOfDay: nil, }, @@ -408,7 +408,7 @@ func TestSetSchedulingPolicyFromFlags(t *testing.T) { startingPolicy: &policy.SchedulingPolicy{ Cron: []string{"1 2 * * *", "2 1 * * *"}, }, - cronArg: "inherit", + cronArg: inheritPolicyString, expResult: &policy.SchedulingPolicy{ Cron: nil, }, @@ -419,7 +419,7 @@ func TestSetSchedulingPolicyFromFlags(t *testing.T) { startingPolicy: &policy.SchedulingPolicy{ TimesOfDay: []policy.TimeOfDay{{Hour: 12, Minute: 0}}, }, - runMissedArg: "true", + runMissedArg: trueStr, expResult: &policy.SchedulingPolicy{ TimesOfDay: []policy.TimeOfDay{{Hour: 12, Minute: 0}}, RunMissed: policy.NewOptionalBool(true), @@ -436,7 +436,7 @@ func TestSetSchedulingPolicyFromFlags(t *testing.T) { TimesOfDay: []policy.TimeOfDay{{Hour: 12, Minute: 0}}, RunMissed: policy.NewOptionalBool(false), }, - runMissedArg: "false", + runMissedArg: falseStr, expChangeCount: 1, }, { diff --git a/cli/command_policy_show.go b/cli/command_policy_show.go index f62a0d897..a1752a799 100644 --- a/cli/command_policy_show.go +++ b/cli/command_policy_show.go @@ -154,10 +154,10 @@ func appendRetentionPolicyRows(rows []policyTableRow, p *policy.Policy, def *pol func boolToString(v bool) string { if v { - return "true" + return trueStr } - return "false" + return falseStr } func logDetailToString(v policy.LogDetail) string { diff --git a/cli/command_repository_connect.go b/cli/command_repository_connect.go index b60372bf1..872bb3991 100644 --- a/cli/command_repository_connect.go +++ b/cli/command_repository_connect.go @@ -72,7 +72,7 @@ func (c *connectOptions) setup(svc appServices, cmd *kingpin.CmdClause) { cmd.Flag("override-hostname", "Override hostname used by this repository connection").Hidden().StringVar(&c.connectHostname) cmd.Flag("override-username", "Override username used by this repository connection").Hidden().StringVar(&c.connectUsername) - cmd.Flag("check-for-updates", "Periodically check for Kopia updates on GitHub").Default("true").Envar(svc.EnvName(checkForUpdatesEnvar)).BoolVar(&c.connectCheckForUpdates) + cmd.Flag("check-for-updates", "Periodically check for Kopia updates on GitHub").Default(trueStr).Envar(svc.EnvName(checkForUpdatesEnvar)).BoolVar(&c.connectCheckForUpdates) cmd.Flag("readonly", "Make repository read-only to avoid accidental changes").BoolVar(&c.connectReadonly) cmd.Flag("permissive-cache-loading", "Do not fail when loading bad cache index entries. Repository must be opened in read-only mode").Hidden().BoolVar(&c.connectPermissiveCacheLoading) cmd.Flag("description", "Human-readable description of the repository").StringVar(&c.connectDescription) diff --git a/cli/command_repository_sync.go b/cli/command_repository_sync.go index bf9142a44..4b10df194 100644 --- a/cli/command_repository_sync.go +++ b/cli/command_repository_sync.go @@ -40,7 +40,7 @@ type commandRepositorySyncTo struct { func (c *commandRepositorySyncTo) setup(svc advancedAppServices, parent commandParent) { cmd := parent.Command("sync-to", "Synchronizes the contents of this repository to another location") - cmd.Flag("update", "Whether to update blobs present in destination and source if the source is newer.").Default("true").BoolVar(&c.repositorySyncUpdate) + cmd.Flag("update", "Whether to update blobs present in destination and source if the source is newer.").Default(trueStr).BoolVar(&c.repositorySyncUpdate) cmd.Flag("delete", "Whether to delete blobs present in destination but not source.").BoolVar(&c.repositorySyncDelete) cmd.Flag("dry-run", "Do not perform copying.").Short('n').BoolVar(&c.repositorySyncDryRun) cmd.Flag("parallel", "Copy parallelism.").Default("1").IntVar(&c.repositorySyncParallelism) diff --git a/cli/command_repository_upgrade.go b/cli/command_repository_upgrade.go index 8a6f3e5ad..da6b49a9c 100644 --- a/cli/command_repository_upgrade.go +++ b/cli/command_repository_upgrade.go @@ -59,10 +59,10 @@ func (c *commandRepositoryUpgrade) setup(svc advancedAppServices, parent command beginCmd := parent.Command("begin", "Begin upgrade.") beginCmd.Flag("io-drain-timeout", "Max time it should take all other Kopia clients to drop repository connections").Default(format.DefaultRepositoryBlobCacheDuration.String()).DurationVar(&c.ioDrainTimeout) - beginCmd.Flag("allow-unsafe-upgrade", "Force using an unsafe io-drain-timeout for the upgrade lock").Default("false").Hidden().BoolVar(&c.allowUnsafeUpgradeTimings) + beginCmd.Flag("allow-unsafe-upgrade", "Force using an unsafe io-drain-timeout for the upgrade lock").Default(falseStr).Hidden().BoolVar(&c.allowUnsafeUpgradeTimings) beginCmd.Flag("status-poll-interval", "An advisory polling interval to check for the status of upgrade").Default("60s").DurationVar(&c.statusPollInterval) beginCmd.Flag("max-permitted-clock-drift", "The maximum drift between repository and client clocks").Default(maxPermittedClockDriftDefault.String()).DurationVar(&c.maxPermittedClockDrift) - beginCmd.Flag("lock-only", "Advertise the upgrade lock and exit without actually performing the drain or upgrade").Default("false").Hidden().BoolVar(&c.lockOnly) // this is used by tests + beginCmd.Flag("lock-only", "Advertise the upgrade lock and exit without actually performing the drain or upgrade").Default(falseStr).Hidden().BoolVar(&c.lockOnly) // this is used by tests beginCmd.Flag("commit-mode", "Change behavior of commit. When not set, commit on validation success. 'always': always commit. 'never': always exit before commit.").Hidden().EnumVar(&c.commitMode, commitModeAlwaysCommit, commitModeNeverCommit) // upgrade phases diff --git a/cli/command_restore.go b/cli/command_restore.go index dabaef308..a1469857f 100644 --- a/cli/command_restore.go +++ b/cli/command_restore.go @@ -141,25 +141,25 @@ func (c *commandRestore) setup(svc appServices, parent commandParent) { cmd := parent.Command("restore", restoreCommandHelp) cmd.Arg("sources", restoreCommandSourcePathHelp).Required().StringsVar(&c.restoreTargetPaths) - cmd.Flag("overwrite-directories", "Overwrite existing directories").Default("true").BoolVar(&c.restoreOverwriteDirectories) - cmd.Flag("overwrite-files", "Specifies whether or not to overwrite already existing files").Default("true").BoolVar(&c.restoreOverwriteFiles) - cmd.Flag("overwrite-symlinks", "Specifies whether or not to overwrite already existing symlinks").Default("true").BoolVar(&c.restoreOverwriteSymlinks) - cmd.Flag("write-sparse-files", "When doing a restore, attempt to write files sparsely-allocating the minimum amount of disk space needed.").Default("false").BoolVar(&c.restoreWriteSparseFiles) + cmd.Flag("overwrite-directories", "Overwrite existing directories").Default(trueStr).BoolVar(&c.restoreOverwriteDirectories) + cmd.Flag("overwrite-files", "Specifies whether or not to overwrite already existing files").Default(trueStr).BoolVar(&c.restoreOverwriteFiles) + cmd.Flag("overwrite-symlinks", "Specifies whether or not to overwrite already existing symlinks").Default(trueStr).BoolVar(&c.restoreOverwriteSymlinks) + cmd.Flag("write-sparse-files", "When doing a restore, attempt to write files sparsely-allocating the minimum amount of disk space needed.").Default(falseStr).BoolVar(&c.restoreWriteSparseFiles) cmd.Flag("consistent-attributes", "When multiple snapshots match, fail if they have inconsistent attributes").Envar(svc.EnvName("KOPIA_RESTORE_CONSISTENT_ATTRIBUTES")).BoolVar(&c.restoreConsistentAttributes) cmd.Flag("mode", "Override restore mode").Default(restoreModeAuto).EnumVar(&c.restoreMode, restoreModeAuto, restoreModeLocal, restoreModeZip, restoreModeZipNoCompress, restoreModeTar, restoreModeTgz) cmd.Flag("parallel", "Restore parallelism (1=disable)").Default("8").IntVar(&c.restoreParallel) cmd.Flag("skip-owners", "Skip owners during restore").BoolVar(&c.restoreSkipOwners) cmd.Flag("skip-permissions", "Skip permissions during restore").BoolVar(&c.restoreSkipPermissions) cmd.Flag("skip-times", "Skip times during restore").BoolVar(&c.restoreSkipTimes) - cmd.Flag("ignore-permission-errors", "Ignore permission errors").Default("true").BoolVar(&c.restoreIgnorePermissionErrors) - cmd.Flag("write-files-atomically", "Write files atomically to disk, ensuring they are either fully committed, or not written at all, preventing partially written files").Default("false").BoolVar(&c.restoreWriteFilesAtomically) + cmd.Flag("ignore-permission-errors", "Ignore permission errors").Default(trueStr).BoolVar(&c.restoreIgnorePermissionErrors) + cmd.Flag("write-files-atomically", "Write files atomically to disk, ensuring they are either fully committed, or not written at all, preventing partially written files").Default(falseStr).BoolVar(&c.restoreWriteFilesAtomically) cmd.Flag("ignore-errors", "Ignore all errors").BoolVar(&c.restoreIgnoreErrors) cmd.Flag("skip-existing", "Skip files and symlinks that exist in the output").BoolVar(&c.restoreIncremental) cmd.Flag("delete-extra", "Delete additional files, directories and symlinks that exist in the restore path but do not exist in the snapshot").BoolVar(&c.restoreDeleteExtra) cmd.Flag("shallow", "Shallow restore the directory hierarchy starting at this level (default is to deep restore the entire hierarchy.)").Int32Var(&c.restoreShallowAtDepth) cmd.Flag("shallow-minsize", "When doing a shallow restore, write actual files instead of placeholders smaller than this size.").Int32Var(&c.minSizeForPlaceholder) cmd.Flag("snapshot-time", "When using a path as the source, use the latest snapshot available before this date. Default is latest").Default("latest").StringVar(&c.snapshotTime) - cmd.Flag("flush-files", "Specifies whether or not to flush files after restore completes").Default("false").BoolVar(&c.flushFiles) + cmd.Flag("flush-files", "Specifies whether or not to flush files after restore completes").Default(falseStr).BoolVar(&c.flushFiles) cmd.Action(svc.repositoryReaderAction(c.run)) } diff --git a/cli/command_server_start.go b/cli/command_server_start.go index 0bae249e9..32593ee1a 100644 --- a/cli/command_server_start.go +++ b/cli/command_server_start.go @@ -88,10 +88,10 @@ type commandServerStart struct { func (c *commandServerStart) setup(svc advancedAppServices, parent commandParent) { cmd := parent.Command("start", "Start Kopia server") cmd.Flag("html", "Server the provided HTML at the root URL").ExistingDirVar(&c.serverStartHTMLPath) - cmd.Flag("ui", "Start the server with HTML UI").Default("true").BoolVar(&c.serverStartUI) + cmd.Flag("ui", "Start the server with HTML UI").Default(trueStr).BoolVar(&c.serverStartUI) - cmd.Flag("grpc", "Start the GRPC server").Default("true").BoolVar(&c.serverStartGRPC) - cmd.Flag("control-api", "Start the control API").Default("true").BoolVar(&c.serverStartControlAPI) + cmd.Flag("grpc", "Start the GRPC server").Default(trueStr).BoolVar(&c.serverStartGRPC) + cmd.Flag("control-api", "Start the control API").Default(trueStr).BoolVar(&c.serverStartControlAPI) cmd.Flag("refresh-interval", "Frequency for refreshing repository status").Default("4h").DurationVar(&c.serverStartRefreshInterval) cmd.Flag("insecure", "Allow insecure configurations (do not use in production)").Hidden().BoolVar(&c.serverStartInsecure) @@ -110,7 +110,7 @@ func (c *commandServerStart) setup(svc advancedAppServices, parent commandParent cmd.Flag("server-control-password", "Server control password").PlaceHolder("PASSWORD").Envar(svc.EnvName("KOPIA_SERVER_CONTROL_PASSWORD")).StringVar(&c.serverControlPassword) cmd.Flag("auth-cookie-signing-key", "Force particular auth cookie signing key").Envar(svc.EnvName("KOPIA_AUTH_COOKIE_SIGNING_KEY")).Hidden().StringVar(&c.serverAuthCookieSingingKey) - cmd.Flag("log-scheduler", "Enable logging of scheduler actions").Hidden().Default("true").BoolVar(&c.debugScheduler) + cmd.Flag("log-scheduler", "Enable logging of scheduler actions").Hidden().Default(trueStr).BoolVar(&c.debugScheduler) cmd.Flag("min-maintenance-interval", "Minimum maintenance interval").Hidden().Default("60s").DurationVar(&c.minMaintenanceInterval) cmd.Flag("shutdown-on-stdin", "Shut down the server when stdin handle has closed.").Hidden().BoolVar(&c.serverStartShutdownWhenStdinClosed) @@ -124,7 +124,7 @@ func (c *commandServerStart) setup(svc advancedAppServices, parent commandParent cmd.Flag("tls-print-server-cert", "Print server certificate").Hidden().BoolVar(&c.serverStartTLSPrintFullServerCert) cmd.Flag("async-repo-connect", "Connect to repository asynchronously").Hidden().BoolVar(&c.asyncRepoConnect) - cmd.Flag("persistent-logs", "Persist logs in a file").Default("true").BoolVar(&c.persistentLogs) + cmd.Flag("persistent-logs", "Persist logs in a file").Default(trueStr).BoolVar(&c.persistentLogs) cmd.Flag("ui-title-prefix", "UI title prefix").Hidden().Envar(svc.EnvName("KOPIA_UI_TITLE_PREFIX")).StringVar(&c.uiTitlePrefix) cmd.Flag("ui-preferences-file", "Path to JSON file storing UI preferences").StringVar(&c.uiPreferencesFile) diff --git a/cli/command_snapshot_create.go b/cli/command_snapshot_create.go index ad1ab74b1..6787463e6 100644 --- a/cli/command_snapshot_create.go +++ b/cli/command_snapshot_create.go @@ -77,9 +77,9 @@ func (c *commandSnapshotCreate) setup(svc appServices, parent commandParent) { cmd.Flag("pin", "Create a pinned snapshot that will not expire automatically").StringsVar(&c.pins) cmd.Flag("flush-per-source", "Flush writes at the end of each source").Hidden().BoolVar(&c.flushPerSource) cmd.Flag("override-source", "Override the source of the snapshot.").StringVar(&c.sourceOverride) - cmd.Flag("send-snapshot-report", "Send a snapshot report notification using configured notification profiles").Default("true").BoolVar(&c.sendSnapshotReport) + cmd.Flag("send-snapshot-report", "Send a snapshot report notification using configured notification profiles").Default(trueStr).BoolVar(&c.sendSnapshotReport) cmd.Flag("hint-streaming-reads", "[EXPERIMENTAL] Hint the OS to release memory used for I/O after reading files that are being backed up, aiming at reducing the memory footprint during backups (Linux only, best-effort)."). - Default("false").Hidden().BoolVar(&c.snapshotCreateStreamingReads) + Default(falseStr).Hidden().BoolVar(&c.snapshotCreateStreamingReads) c.logDirDetail = -1 c.logEntryDetail = -1 diff --git a/cli/command_snapshot_list.go b/cli/command_snapshot_list.go index 923efdbfd..ea980bbd1 100644 --- a/cli/command_snapshot_list.go +++ b/cli/command_snapshot_list.go @@ -45,10 +45,10 @@ func (c *commandSnapshotList) setup(svc appServices, parent commandParent) { cmd := parent.Command("list", "List snapshots of files and directories.").Alias("ls") cmd.Arg("source", "File or directory to show history of.").StringVar(&c.snapshotListPath) cmd.Flag("incomplete", "Include incomplete.").Short('i').BoolVar(&c.snapshotListIncludeIncomplete) - cmd.Flag("human-readable", "Show human-readable units").Default("true").BoolVar(&c.snapshotListShowHumanReadable) + cmd.Flag("human-readable", "Show human-readable units").Default(trueStr).BoolVar(&c.snapshotListShowHumanReadable) cmd.Flag("delta", "Include deltas.").Short('d').BoolVar(&c.snapshotListShowDelta) cmd.Flag("manifest-id", "Include manifest item ID.").Short('m').BoolVar(&c.snapshotListShowItemID) - cmd.Flag("retention", "Include retention reasons.").Default("true").BoolVar(&c.snapshotListShowRetentionReasons) + cmd.Flag("retention", "Include retention reasons.").Default(trueStr).BoolVar(&c.snapshotListShowRetentionReasons) cmd.Flag("mtime", "Include file mod time").BoolVar(&c.snapshotListShowModTime) cmd.Flag("owner", "Include owner").BoolVar(&c.snapshotListShowOwner) cmd.Flag("show-identical", "Show identical snapshots").Short('l').BoolVar(&c.snapshotListShowIdentical) diff --git a/cli/command_snapshot_migrate.go b/cli/command_snapshot_migrate.go index 175e88ff3..8b310aa5c 100644 --- a/cli/command_snapshot_migrate.go +++ b/cli/command_snapshot_migrate.go @@ -34,7 +34,7 @@ func (c *commandSnapshotMigrate) setup(svc advancedAppServices, parent commandPa cmd.Flag("source-config", "Configuration file for the source repository").Required().ExistingFileVar(&c.migrateSourceConfig) cmd.Flag("sources", "List of sources to migrate").StringsVar(&c.migrateSources) cmd.Flag("all", "Migrate all sources").BoolVar(&c.migrateAll) - cmd.Flag("policies", "Migrate policies too").Default("true").BoolVar(&c.migratePolicies) + cmd.Flag("policies", "Migrate policies too").Default(trueStr).BoolVar(&c.migratePolicies) cmd.Flag("overwrite-policies", "Overwrite policies").BoolVar(&c.migrateOverwritePolicies) cmd.Flag("latest-only", "Only migrate the latest snapshot").BoolVar(&c.migrateLatestOnly) cmd.Flag("parallel", "Number of sources to migrate in parallel").Default("1").IntVar(&c.migrateParallel) diff --git a/cli/password_darwin.go b/cli/password_darwin.go index 219527a20..651c0490e 100644 --- a/cli/password_darwin.go +++ b/cli/password_darwin.go @@ -5,5 +5,5 @@ ) func (c *App) setupOSSpecificKeychainFlags(_ appServices, app *kingpin.Application) { - app.Flag("use-keychain", "Use macOS Keychain for storing repository password.").Default("true").BoolVar(&c.keyRingEnabled) + app.Flag("use-keychain", "Use macOS Keychain for storing repository password.").Default(trueStr).BoolVar(&c.keyRingEnabled) } diff --git a/cli/password_linux.go b/cli/password_linux.go index adc985bb4..b9bfbf852 100644 --- a/cli/password_linux.go +++ b/cli/password_linux.go @@ -5,5 +5,5 @@ ) func (c *App) setupOSSpecificKeychainFlags(svc appServices, app *kingpin.Application) { - app.Flag("use-keyring", "Use Gnome Keyring for storing repository password.").Default("false").Envar(svc.EnvName("KOPIA_USE_KEYRING")).BoolVar(&c.keyRingEnabled) + app.Flag("use-keyring", "Use Gnome Keyring for storing repository password.").Default(falseStr).Envar(svc.EnvName("KOPIA_USE_KEYRING")).BoolVar(&c.keyRingEnabled) } diff --git a/cli/password_windows.go b/cli/password_windows.go index 5223724a1..4933c2c7e 100644 --- a/cli/password_windows.go +++ b/cli/password_windows.go @@ -5,5 +5,5 @@ ) func (c *App) setupOSSpecificKeychainFlags(_ appServices, app *kingpin.Application) { - app.Flag("use-credential-manager", "Use Windows Credential Manager for storing repository password.").Default("true").BoolVar(&c.keyRingEnabled) + app.Flag("use-credential-manager", "Use Windows Credential Manager for storing repository password.").Default(trueStr).BoolVar(&c.keyRingEnabled) } diff --git a/cli/storage_rclone.go b/cli/storage_rclone.go index f5dc4d47d..02ae71115 100644 --- a/cli/storage_rclone.go +++ b/cli/storage_rclone.go @@ -29,7 +29,7 @@ func (c *storageRcloneFlags) Setup(_ StorageProviderServices, cmd *kingpin.CmdCl cmd.Flag("rclone-debug", "Log rclone output").Hidden().BoolVar(&c.opt.Debug) cmd.Flag("rclone-nowait-for-transfers", "Don't wait for transfers when closing storage").Hidden().BoolVar(&c.opt.NoWaitForTransfers) cmd.Flag("list-parallelism", "Set list parallelism").Hidden().IntVar(&c.opt.ListParallelism) - cmd.Flag("atomic-writes", "Assume provider writes are atomic").Default("true").BoolVar(&c.opt.AtomicWrites) + cmd.Flag("atomic-writes", "Assume provider writes are atomic").Default(trueStr).BoolVar(&c.opt.AtomicWrites) cmd.Flag("rclone-startup-timeout", "Time in seconds to wait for rclone to start").Default("15s").DurationVar(&c.opt.StartupTimeout.Duration) commonThrottlingFlags(cmd, &c.opt.Limits) diff --git a/internal/bigmap/bigmap_internal.go b/internal/bigmap/bigmap_internal.go index ae5d7a3f4..0804b01fe 100644 --- a/internal/bigmap/bigmap_internal.go +++ b/internal/bigmap/bigmap_internal.go @@ -14,6 +14,7 @@ "context" "encoding/binary" "os" + "slices" "sync" "github.com/edsrzf/mmap-go" @@ -393,8 +394,8 @@ func (m *internalMap) Close(_ context.Context) { m.mu.Lock() defer m.mu.Unlock() - for i := len(m.cleanups) - 1; i >= 0; i-- { - m.cleanups[i]() + for _, v := range slices.Backward(m.cleanups) { + v() } m.cleanups = nil diff --git a/internal/logfile/logfile.go b/internal/logfile/logfile.go index 51f310e1b..904ed0641 100644 --- a/internal/logfile/logfile.go +++ b/internal/logfile/logfile.go @@ -155,20 +155,19 @@ func (c *loggingFlags) setupConsoleCore() zapcore.Core { ConsoleSeparator: " ", } - timeFormat := zaplogutil.PreciseLayout + timeFormat := "" if c.consoleLogTimestamps { ec.TimeKey = "t" if c.jsonLogConsole { + timeFormat = zaplogutil.PreciseLayout ec.EncodeTime = zapcore.RFC3339NanoTimeEncoder } else { // always log local timestamps to the console, not UTC timeFormat = "15:04:05.000" ec.EncodeTime = zaplogutil.TimezoneAdjust(zapcore.TimeEncoderOfLayout(timeFormat), true) } - } else { - timeFormat = "" } stec := zaplogutil.StdConsoleEncoderConfig{ diff --git a/internal/scrubber/scrub_sensitive.go b/internal/scrubber/scrub_sensitive.go index 22ce4d3b8..e1ad8108b 100644 --- a/internal/scrubber/scrub_sensitive.go +++ b/internal/scrubber/scrub_sensitive.go @@ -10,7 +10,7 @@ // Fields are marked as sensitive with struct field tag `kopia:"sensitive"`. func ScrubSensitiveData(v reflect.Value) reflect.Value { switch v.Kind() { - case reflect.Ptr: + case reflect.Pointer: return ScrubSensitiveData(v.Elem()).Addr() case reflect.Struct: diff --git a/internal/server/server.go b/internal/server/server.go index 6c41021a3..a6e2479a2 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -447,9 +447,7 @@ func (s *Server) Refresh() { s.serverMutex.Lock() defer s.serverMutex.Unlock() - ctx := s.rootctx - - if err := s.refreshLocked(ctx); err != nil { + if err := s.refreshLocked(s.rootctx); err != nil { userLog(s.rootctx).Warnw("refresh error", "err", err) } } diff --git a/internal/uitask/uitask_counter.go b/internal/uitask/uitask_counter.go index 00b6746a9..8028b676f 100644 --- a/internal/uitask/uitask_counter.go +++ b/internal/uitask/uitask_counter.go @@ -7,9 +7,11 @@ type CounterValue struct { Level string `json:"level"` // "", "notice", "warning" or "error" } +const bytesString = "bytes" + // BytesCounter returns CounterValue for the number of bytes. func BytesCounter(v int64) CounterValue { - return CounterValue{v, "bytes", ""} + return CounterValue{v, bytesString, ""} } // SimpleCounter returns simple numeric CounterValue without units. @@ -19,7 +21,7 @@ func SimpleCounter(v int64) CounterValue { // NoticeBytesCounter returns CounterValue for the number of bytes. func NoticeBytesCounter(v int64) CounterValue { - return CounterValue{v, "bytes", "notice"} + return CounterValue{v, bytesString, "notice"} } // NoticeCounter returns simple numeric CounterValue without units. @@ -29,7 +31,7 @@ func NoticeCounter(v int64) CounterValue { // WarningBytesCounter returns CounterValue for the number of bytes. func WarningBytesCounter(v int64) CounterValue { - return CounterValue{v, "bytes", "warning"} + return CounterValue{v, bytesString, "warning"} } // WarningCounter returns simple numeric CounterValue without units. @@ -39,7 +41,7 @@ func WarningCounter(v int64) CounterValue { // ErrorBytesCounter returns CounterValue for the number of bytes. func ErrorBytesCounter(v int64) CounterValue { - return CounterValue{v, "bytes", "error"} + return CounterValue{v, bytesString, "error"} } // ErrorCounter returns simple numeric CounterValue without units. diff --git a/repo/blob/sharded/sharded_parameters.go b/repo/blob/sharded/sharded_parameters.go index e6169ff42..907b417f0 100644 --- a/repo/blob/sharded/sharded_parameters.go +++ b/repo/blob/sharded/sharded_parameters.go @@ -49,7 +49,7 @@ func (p *Parameters) Save(w io.Writer) error { func cloneShards(v []int) []int { if v != nil { - return append(([]int(nil)), v...) + return append([]int(nil), v...) } return nil diff --git a/repo/buildinfo.go b/repo/buildinfo.go index 66c266c8a..95ce4aef7 100644 --- a/repo/buildinfo.go +++ b/repo/buildinfo.go @@ -66,7 +66,7 @@ func getRevisionString(s []debug.BuildSetting) string { case "vcs.time": vcsTime = v.Value case "vcs.modified": - if strings.EqualFold(v.Value, "true") { + if strings.EqualFold(v.Value, trueStr) { modified = true } } diff --git a/repo/buildinfo_test.go b/repo/buildinfo_test.go index 5164ff7fd..de423490b 100644 --- a/repo/buildinfo_test.go +++ b/repo/buildinfo_test.go @@ -19,7 +19,7 @@ func TestGetRevisionString(t *testing.T) { input: []debug.BuildSetting{ { Key: "vcs.modified", - Value: "true", + Value: trueStr, }, }, want: "-(unknown_revision)+dirty", @@ -41,7 +41,7 @@ func TestGetRevisionString(t *testing.T) { }, { Key: "vcs.modified", - Value: "true", + Value: trueStr, }, }, want: "2025-04-12T16:01:30Z-(unknown_revision)+dirty", @@ -97,7 +97,7 @@ func TestGetRevisionString(t *testing.T) { }, { Key: "vcs.modified", - Value: "true", + Value: trueStr, }, }, want: "2025-04-12T16:01:30Z-353676da445938316fa00b2b812a61f4b1dd3ffa+dirty", diff --git a/repo/connect.go b/repo/connect.go index 3827bee3b..182d7c31d 100644 --- a/repo/connect.go +++ b/repo/connect.go @@ -47,11 +47,11 @@ func Connect(ctx context.Context, configFile string, st blob.Storage, password s return err } - var lc LocalConfig - ci := st.ConnectionInfo() - lc.Storage = &ci - lc.ClientOptions = opt.ApplyDefaults(ctx, "Repository in "+st.DisplayName()) + lc := LocalConfig{ + Storage: &ci, + ClientOptions: opt.ApplyDefaults(ctx, "Repository in "+st.DisplayName()), + } if err = setupCachingOptionsWithDefaults(ctx, configFile, &lc, &opt.CachingOptions, f.UniqueID); err != nil { return errors.Wrap(err, "unable to set up caching") diff --git a/repo/content/content_manager_test.go b/repo/content/content_manager_test.go index f4a011da3..683853ecb 100644 --- a/repo/content/content_manager_test.go +++ b/repo/content/content_manager_test.go @@ -265,7 +265,7 @@ func (s *contentManagerSuite) TestContentManagerInternalFlush(t *testing.T) { defer bm.CloseShared(ctx) - itemsToOverflow := (maxPackCapacity)/(25+encryptionOverhead) + 2 + itemsToOverflow := maxPackCapacity/(25+encryptionOverhead) + 2 for range itemsToOverflow { b := make([]byte, 25) cryptorand.Read(b) diff --git a/repo/manifest/committed_manifest_manager.go b/repo/manifest/committed_manifest_manager.go index b533d688b..765014c87 100644 --- a/repo/manifest/committed_manifest_manager.go +++ b/repo/manifest/committed_manifest_manager.go @@ -274,7 +274,7 @@ func (m *committedManifestManager) compactLocked(ctx context.Context) error { } if err := m.b.DeleteContent(ctx, b); err != nil { - return errors.Wrapf(err, "unable to delete content %q", b) + return errors.Wrapf(err, "unable to delete manifest content %q", b) } delete(m.committedContentIDs, b) diff --git a/repo/repository.go b/repo/repository.go index 8f2efd4aa..893f43898 100644 --- a/repo/repository.go +++ b/repo/repository.go @@ -24,6 +24,8 @@ "github.com/kopia/kopia/repo/object" ) +const trueStr = "true" + var tracer = otel.Tracer("kopia/repository") // Repository exposes public API of Kopia repository, including objects and manifests. diff --git a/snapshot/policy/policy_tree.go b/snapshot/policy/policy_tree.go index 820d7c239..6ae6def63 100644 --- a/snapshot/policy/policy_tree.go +++ b/snapshot/policy/policy_tree.go @@ -195,7 +195,7 @@ func childrenWithPrefix(m map[string]*Policy, path string) map[string]map[string continue } - childName := strings.Split(k[len(path):], "/")[0] + childName, _, _ := strings.Cut(k[len(path):], "/") if result[childName] == nil { result[childName] = map[string]*Policy{} } diff --git a/tests/end_to_end_test/acl_test.go b/tests/end_to_end_test/acl_test.go index 548c92e65..0905dea02 100644 --- a/tests/end_to_end_test/acl_test.go +++ b/tests/end_to_end_test/acl_test.go @@ -125,27 +125,23 @@ func TestACL(t *testing.T) { foobarClientEnvironment.RunAndExpectSuccess(t, "snapshot", "create", sharedTestDataDir1) // foo@bar sees one snapshot - if snaps := clitestutil.ListSnapshotsAndExpectSuccess(t, foobarClientEnvironment, "-a"); len(snaps) != 1 { - t.Fatalf("foo@bar expected to see 1 sources (own, got %v", snaps) - } + snaps := clitestutil.ListSnapshotsAndExpectSuccess(t, foobarClientEnvironment, "-a") + require.Len(t, snaps, 1, "foo@bar expected to see 1 source (own)") - // alice@wonderland sees zero sources - if snaps := clitestutil.ListSnapshotsAndExpectSuccess(t, aliceInWonderlandClientEnvironment, "-a"); len(snaps) != 0 { - t.Fatalf("foo@bar expected to see 0 sources (own), got %v", snaps) - } + // alice@wonderland sees zero snapshot sources + snaps = clitestutil.ListSnapshotsAndExpectSuccess(t, aliceInWonderlandClientEnvironment, "-a") + require.Empty(t, snaps, "alice@wonderland expected to see 0 sources (own)") // alice@wonderland takes a snapshot now aliceInWonderlandClientEnvironment.RunAndExpectSuccess(t, "snapshot", "create", sharedTestDataDir1) // foo@bar now can see two snapshot sources (own and alice's) - if snaps := clitestutil.ListSnapshotsAndExpectSuccess(t, foobarClientEnvironment, "-a"); len(snaps) != 2 { - t.Fatalf("foo@bar expected to see 2 sources (own and alice), got %v", snaps) - } + snaps = clitestutil.ListSnapshotsAndExpectSuccess(t, foobarClientEnvironment, "-a") + require.Len(t, snaps, 2, "foo@bar expected to see 2 sources (own and alice's)") // alice@wonderland can only see her own - if snaps := clitestutil.ListSnapshotsAndExpectSuccess(t, aliceInWonderlandClientEnvironment, "-a"); len(snaps) != 1 { - t.Fatalf("foo@bar expected to see 1 source (own), got %v", snaps) - } + snaps = clitestutil.ListSnapshotsAndExpectSuccess(t, aliceInWonderlandClientEnvironment, "-a") + require.Len(t, snaps, 1, "alice@wonderland expected to see 1 source (own)") // another@bar can create snapshots but not delete them anotherBarClientEnvironment.RunAndExpectSuccess(t, "snapshot", "create", sharedTestDataDir1) diff --git a/tests/end_to_end_test/auto_update_test.go b/tests/end_to_end_test/auto_update_test.go index 0f38f8303..62286db5b 100644 --- a/tests/end_to_end_test/auto_update_test.go +++ b/tests/end_to_end_test/auto_update_test.go @@ -22,13 +22,13 @@ func TestAutoUpdateEnableTest(t *testing.T) { }{ {desc: "Default", wantEnabled: true, wantInitialDelay: 24 * time.Hour}, {desc: "DisabledByFlag", extraArgs: []string{"--no-check-for-updates"}, wantEnabled: false}, - {desc: "DisabledByEnvar-false", extraEnv: map[string]string{"KOPIA_CHECK_FOR_UPDATES": "false"}, wantEnabled: false}, + {desc: "DisabledByEnvar-false", extraEnv: map[string]string{"KOPIA_CHECK_FOR_UPDATES": falseStr}, wantEnabled: false}, {desc: "DisabledByEnvar-0", extraEnv: map[string]string{"KOPIA_CHECK_FOR_UPDATES": "0"}, wantEnabled: false}, {desc: "DisabledByEnvar-f", extraEnv: map[string]string{"KOPIA_CHECK_FOR_UPDATES": "f"}, wantEnabled: false}, {desc: "DisabledByEnvar-False", extraEnv: map[string]string{"KOPIA_CHECK_FOR_UPDATES": "False"}, wantEnabled: false}, {desc: "DisabledByEnvar-FALSE", extraEnv: map[string]string{"KOPIA_CHECK_FOR_UPDATES": "FALSE"}, wantEnabled: false}, {desc: "DisabledByEnvarOverriddenByFlag", extraEnv: map[string]string{"KOPIA_CHECK_FOR_UPDATES": "false"}, extraArgs: []string{"--check-for-updates"}, wantEnabled: true, wantInitialDelay: 24 * time.Hour}, - {desc: "EnabledByEnvarOverriddenByFlag", extraEnv: map[string]string{"KOPIA_CHECK_FOR_UPDATES": "true"}, extraArgs: []string{"--no-check-for-updates"}, wantEnabled: false, wantInitialDelay: 24 * time.Hour}, + {desc: "EnabledByEnvarOverriddenByFlag", extraEnv: map[string]string{"KOPIA_CHECK_FOR_UPDATES": trueStr}, extraArgs: []string{"--no-check-for-updates"}, wantEnabled: false, wantInitialDelay: 24 * time.Hour}, {desc: "InitialUpdateCheckIntervalFlag", extraEnv: map[string]string{"KOPIA_INITIAL_UPDATE_CHECK_DELAY": "1h"}, wantEnabled: true, wantInitialDelay: 1 * time.Hour}, {desc: "InitialUpdateCheckIntervalEnvar", extraArgs: []string{"--initial-update-check-delay=3h"}, wantEnabled: true, wantInitialDelay: 3 * time.Hour}, diff --git a/tests/end_to_end_test/index_recover_test.go b/tests/end_to_end_test/index_recover_test.go index f2c520454..6c7e28144 100644 --- a/tests/end_to_end_test/index_recover_test.go +++ b/tests/end_to_end_test/index_recover_test.go @@ -36,7 +36,7 @@ func (s *formatSpecificTestSuite) TestIndexRecover(t *testing.T) { lines := e.RunAndVerifyOutputLineCount(t, 6, "index", "ls") for _, l := range lines { - indexFile := strings.Split(l, " ")[0] + indexFile, _, _ := strings.Cut(l, " ") e.RunAndExpectSuccess(t, "blob", "delete", indexFile) } diff --git a/tests/end_to_end_test/main_test.go b/tests/end_to_end_test/main_test.go index 7dca74914..eff6a8abe 100644 --- a/tests/end_to_end_test/main_test.go +++ b/tests/end_to_end_test/main_test.go @@ -13,6 +13,11 @@ "github.com/kopia/kopia/tests/testdirtree" ) +const ( + falseStr = "false" + trueStr = "true" +) + var ( sharedTestDataDirBase string sharedTestDataDir1 string diff --git a/tests/end_to_end_test/repository_set_client_test.go b/tests/end_to_end_test/repository_set_client_test.go index b9e2e709a..f0ca5cca6 100644 --- a/tests/end_to_end_test/repository_set_client_test.go +++ b/tests/end_to_end_test/repository_set_client_test.go @@ -27,7 +27,7 @@ func (s *formatSpecificTestSuite) TestRepositorySetClient(t *testing.T) { return strings.Contains(l, "Description:") && strings.Contains(l, "My Repo") }) verifyHasLine(t, sl, func(l string) bool { - return strings.Contains(l, "Read-only:") && strings.Contains(l, "false") + return strings.Contains(l, "Read-only:") && strings.Contains(l, falseStr) }) verifyHasLine(t, sl, func(l string) bool { return strings.Contains(l, "Username:") && strings.Contains(l, "myuser") @@ -51,7 +51,7 @@ func (s *formatSpecificTestSuite) TestRepositorySetClient(t *testing.T) { return strings.Contains(l, "Description:") && strings.Contains(l, "My Updated Repo") }) verifyHasLine(t, sl, func(l string) bool { - return strings.Contains(l, "Read-only:") && strings.Contains(l, "true") + return strings.Contains(l, "Read-only:") && strings.Contains(l, trueStr) }) verifyHasLine(t, sl, func(l string) bool { return strings.Contains(l, "Hostname:") && strings.Contains(l, "my-updated-host") diff --git a/tests/end_to_end_test/server_start_test.go b/tests/end_to_end_test/server_start_test.go index 4d8dc49f9..50631d856 100644 --- a/tests/end_to_end_test/server_start_test.go +++ b/tests/end_to_end_test/server_start_test.go @@ -258,7 +258,7 @@ func TestServerStartAsyncRepoConnect(t *testing.T) { } func TestServerCreateAndConnectViaAPI(t *testing.T) { - t.Setenv("KOPIA_UPGRADE_LOCK_ENABLED", "true") + t.Setenv("KOPIA_UPGRADE_LOCK_ENABLED", trueStr) ctx := testlogging.Context(t) diff --git a/tests/end_to_end_test/snapshot_create_test.go b/tests/end_to_end_test/snapshot_create_test.go index 968325dfd..34654ba37 100644 --- a/tests/end_to_end_test/snapshot_create_test.go +++ b/tests/end_to_end_test/snapshot_create_test.go @@ -79,7 +79,7 @@ func TestSnapshotCreate(t *testing.T) { require.Len(t, sources, 3) // test ignore-identical-snapshot - e.RunAndExpectSuccess(t, "policy", "set", "--global", "--ignore-identical-snapshots", "true") + e.RunAndExpectSuccess(t, "policy", "set", "--global", "--ignore-identical-snapshots", trueStr) e.RunAndExpectSuccess(t, "snapshot", "create", sharedTestDataDir2) testutil.MustParseJSONLines(t, e.RunAndExpectSuccess(t, "snapshot", "list", "-a", "--json"), &manifests) diff --git a/tests/end_to_end_test/snapshot_fail_test.go b/tests/end_to_end_test/snapshot_fail_test.go index 2c2fbd47f..0c75f1c7c 100644 --- a/tests/end_to_end_test/snapshot_fail_test.go +++ b/tests/end_to_end_test/snapshot_fail_test.go @@ -48,7 +48,7 @@ func TestSnapshotFail_DefaultJSONOutput(t *testing.T) { func TestSnapshotFail_EnvOverride(t *testing.T) { t.Parallel() - testSnapshotFailText(t, true, nil, map[string]string{"KOPIA_SNAPSHOT_FAIL_FAST": "true"}) + testSnapshotFailText(t, true, nil, map[string]string{"KOPIA_SNAPSHOT_FAIL_FAST": trueStr}) } func TestSnapshotFail_NoFailFast(t *testing.T) { @@ -99,17 +99,17 @@ func testSnapshotFail( t.Skip("this test does not work as root, because we're unable to remove permissions.") } - for _, ignoreFileErr := range []string{"true", "false"} { - // Use "inherit" instead of "false" sometimes. Inherit defaults to false - if ignoreFileErr == "false" && rand.Intn(2) == 0 { + for _, ignoreFileErr := range []string{trueStr, falseStr} { + // Use "inherit" instead of falseStr sometimes. Inherit defaults to false + if ignoreFileErr == falseStr && rand.Intn(2) == 0 { ignoreFileErr = "inherit" } t.Run(fmt.Sprintf("failFast=%v:ignoreFileErr=%s", isFailFast, ignoreFileErr), func(t *testing.T) { t.Parallel() - for _, ignoreDirErr := range []string{"true", "false"} { - if ignoreDirErr == "false" && rand.Intn(2) == 0 { + for _, ignoreDirErr := range []string{trueStr, falseStr} { + if ignoreDirErr == falseStr && rand.Intn(2) == 0 { ignoreDirErr = "inherit" } @@ -139,8 +139,8 @@ func testSnapshotFailCases( const dir0Path = "dir0" var ( - ignoringDirs = ignoreDirErr == "true" - ignoringFiles = ignoreFileErr == "true" + ignoringDirs = ignoreDirErr == trueStr + ignoringFiles = ignoreFileErr == trueStr expectedSuccess = expectedSnapshotResult{success: true} expectEarlyFailure = expectedSnapshotResult{success: false} diff --git a/tests/robustness/snapmeta/kopia_persister.go b/tests/robustness/snapmeta/kopia_persister.go index 103b10dd2..7a57a539a 100644 --- a/tests/robustness/snapmeta/kopia_persister.go +++ b/tests/robustness/snapmeta/kopia_persister.go @@ -134,7 +134,7 @@ func (store *KopiaPersister) LoadMetadata() error { return err } - err = json.NewDecoder(f).Decode(&(store.Simple)) + err = json.NewDecoder(f).Decode(&store.Simple) if err != nil { return err } diff --git a/tests/testenv/cli_test_env.go b/tests/testenv/cli_test_env.go index 0d4c19664..57ad3180e 100644 --- a/tests/testenv/cli_test_env.go +++ b/tests/testenv/cli_test_env.go @@ -215,7 +215,9 @@ func (e *CLITest) RunAndProcessStderrInt(tb testing.TB, stderrCallback func(line } } - if logOutput { + if err := scanner.Err(); err != nil { + tb.Logf("Error reading [%sstdout]: %v", prefix, err) + } else if logOutput { tb.Logf("[%vstdout] EOF", prefix) } }() @@ -239,7 +241,9 @@ func (e *CLITest) RunAndProcessStderrInt(tb testing.TB, stderrCallback func(line } } - if logOutput { + if err := scanner.Err(); err != nil { + tb.Logf("Error reading [%sstderr]: %v", prefix, err) + } else if logOutput { tb.Logf("[%vstderr] EOF", prefix) } }() @@ -314,6 +318,10 @@ func (e *CLITest) Run(tb testing.TB, expectedError bool, args ...string) (stdout stdout = append(stdout, scanner.Text()) } + + if err := scanner.Err(); err != nil { + tb.Logf("Error reading [%sstdout]: %v", outputPrefix, err) + } }) wg.Go(func() { @@ -325,6 +333,10 @@ func (e *CLITest) Run(tb testing.TB, expectedError bool, args ...string) (stdout stderr = append(stderr, scanner.Text()) } + + if err := scanner.Err(); err != nil { + tb.Logf("Error reading [%sstderr]: %v", outputPrefix, err) + } }) wg.Wait() diff --git a/tools/cli2md/cli2md.go b/tools/cli2md/cli2md.go index e3d226c49..f293660c0 100644 --- a/tools/cli2md/cli2md.go +++ b/tools/cli2md/cli2md.go @@ -261,7 +261,7 @@ func generateSubcommands(w io.Writer, dir, sectionTitle string, cmds []*kingpin. } subcommandSlug := strings.ReplaceAll(c.FullCommand, " ", "-") - helpSummary := strings.SplitN(c.Help, "\n", 2)[0] //nolint:mnd + helpSummary, _, _ := strings.Cut(c.Help, "\n") helpSummary = strings.TrimSuffix(helpSummary, ".") fmt.Fprintf(w, "* [`%v`](%v) - %v\n", c.FullCommand, subcommandSlug+"/", helpSummary) //nolint:errcheck generateSubcommandPage(filepath.Join(dir, subcommandSlug+".md"), c) diff --git a/tools/gettool/gettool.go b/tools/gettool/gettool.go index 545f49e3c..3054c441e 100644 --- a/tools/gettool/gettool.go +++ b/tools/gettool/gettool.go @@ -31,6 +31,17 @@ type ToolInfo struct { macosUniversalArch string } +const ( + amd64 = "amd64" + arm = "arm" + arm64 = "arm64" + armv6 = "armv6" + darwin = "darwin" + linux = "linux" + windows = "windows" + targz = "tar.gz" +) + func (ti ToolInfo) actualURL(version, goos, goarch string) string { if ti.unsupportedArch[goarch] { return "" @@ -43,16 +54,16 @@ func (ti ToolInfo) actualURL(version, goos, goarch string) string { u := ti.urlTemplate u = strings.ReplaceAll(u, "VERSION", version) - if goos == "darwin" && ti.macosUniversalArch != "" { + if goos == darwin && ti.macosUniversalArch != "" { goarch = ti.macosUniversalArch } u = strings.ReplaceAll(u, "GOARCH", replacementFromMap(goarch, ti.archMap)) u = strings.ReplaceAll(u, "GOOS", replacementFromMap(goos, ti.osMap)) u = strings.ReplaceAll(u, "EXT", replacementFromMap(goos, map[string]string{ - "windows": "zip", - "linux": "tar.gz", - "darwin": "tar.gz", + windows: "zip", + linux: targz, + darwin: targz, })) return u @@ -63,14 +74,14 @@ func (ti ToolInfo) actualURL(version, goos, goarch string) string { "linter": { urlTemplate: "https://github.com/golangci/golangci-lint/releases/download/vVERSION/golangci-lint-VERSION-GOOS-GOARCH.EXT", archMap: map[string]string{ - "arm": "armv6", + arm: armv6, }, stripPathComponents: 1, }, "hugo": { urlTemplate: "https://github.com/gohugoio/hugo/releases/download/vVERSION/hugo_extended_VERSION_GOOS-GOARCH.EXT", unsupportedArch: map[string]bool{ - "arm": true, + arm: true, }, unsupportedOSArch: map[string]bool{ "linux/arm64": true, @@ -80,46 +91,46 @@ func (ti ToolInfo) actualURL(version, goos, goarch string) string { "gotestsum": { urlTemplate: "https://github.com/gotestyourself/gotestsum/releases/download/vVERSION/gotestsum_VERSION_GOOS_GOARCH.tar.gz", archMap: map[string]string{ - "arm": "armv6", + arm: armv6, }, }, "kopia": { urlTemplate: "https://github.com/kopia/kopia/releases/download/vVERSION/kopia-VERSION-GOOS-GOARCH.EXT", archMap: map[string]string{ - "amd64": "x64", + amd64: "x64", }, osMap: map[string]string{ - "darwin": "macOS", + darwin: "macOS", }, stripPathComponents: 1, }, "rclone": { urlTemplate: "https://github.com/rclone/rclone/releases/download/vVERSION/rclone-vVERSION-GOOS-GOARCH.zip", - osMap: map[string]string{"darwin": "osx"}, + osMap: map[string]string{darwin: "osx"}, stripPathComponents: 1, }, "goreleaser": { urlTemplate: "https://github.com/goreleaser/goreleaser/releases/download/VERSION/goreleaser_GOOS_GOARCH.EXT", archMap: map[string]string{ - "amd64": "x86_64", - "arm": "armv6", + amd64: "x86_64", + arm: armv6, }, osMap: map[string]string{ - "darwin": "Darwin", - "linux": "Linux", - "windows": "Windows", + darwin: "Darwin", + linux: "Linux", + windows: "Windows", }, }, "gitchglog": { urlTemplate: "https://github.com/git-chglog/git-chglog/releases/download/vVERSION/git-chglog_VERSION_GOOS_GOARCH.EXT", archMap: map[string]string{ - "arm": "armv6", + arm: armv6, }, }, "node": { urlTemplate: "https://nodejs.org/dist/vVERSION/node-vVERSION-GOOS-GOARCH.EXT", - osMap: map[string]string{"windows": "win"}, - archMap: map[string]string{"arm": "armv7l", "amd64": "x64"}, + osMap: map[string]string{windows: "win"}, + archMap: map[string]string{arm: "armv7l", amd64: "x64"}, stripPathComponents: 1, }, } @@ -140,12 +151,12 @@ func (ti ToolInfo) actualURL(version, goos, goarch string) string { goos string goarch string }{ - {"linux", "amd64"}, - {"linux", "arm64"}, - {"linux", "arm"}, - {"darwin", "amd64"}, - {"darwin", "arm64"}, - {"windows", "amd64"}, + {linux, amd64}, + {linux, arm64}, + {linux, arm}, + {darwin, amd64}, + {darwin, arm64}, + {windows, amd64}, } func replacementFromMap(defaultValue string, m map[string]string) string {