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
This commit is contained in:
Julio López authored and GitHub committed 2026-09-06 15:08:49 -07:00
1 parent f3a4083c98
commit fdf0159a17
49 files changed
+193 -156

No files matched your search

+9 -4
View File
@@ -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).
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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))
+3 -3
View File
@@ -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)
}
+16 -10
View File
@@ -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 {
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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")
+3 -3
View File
@@ -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)
+1 -1
View File
@@ -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))
+3 -3
View File
@@ -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 {
+19 -19
View File
@@ -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,
},
{
+2 -2
View File
@@ -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 {
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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
+7 -7
View File
@@ -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))
}
+5 -5
View File
@@ -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)
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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)
}
+1 -1
View File
@@ -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)
}
+1 -1
View File
@@ -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)
}
+1 -1
View File
@@ -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)
+3 -2
View File
@@ -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
+2 -3
View File
@@ -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{
+1 -1
View File
@@ -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:
+1 -3
View File
@@ -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)
}
}
+6 -4
View File
@@ -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.
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
}
}
+3 -3
View File
@@ -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",
+4 -4
View File
@@ -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")
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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)
+2
View File
@@ -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.
+1 -1
View File
@@ -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{}
}
+9 -13
View File
@@ -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)
+2 -2
View File
@@ -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},
+1 -1
View File
@@ -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)
}
+5
View File
@@ -13,6 +13,11 @@
"github.com/kopia/kopia/tests/testdirtree"
)
const (
falseStr = "false"
trueStr = "true"
)
var (
sharedTestDataDirBase string
sharedTestDataDir1 string
@@ -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")
+1 -1
View File
@@ -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)
@@ -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)
+8 -8
View File
@@ -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}
+1 -1
View File
@@ -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
}
+14 -2
View File
@@ -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()
+1 -1
View File
@@ -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)
+35 -24
View File
@@ -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 {