Repository: kopia/kopia
Pull request #2631 (2022-12-05 23:05:09)

build(deps): bump go.uber.org/zap from 1.23.0 to 1.24.0
Bumps [go.uber.org/zap](https://github.com/uber-go/zap) from 1.23.0 to 1.24.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/uber-go/zap/releases">go.uber.org/zap's releases</a>.</em></p>
<blockquote>
<h2>v1.24.0</h2>
<p>Enhancements:</p>
<ul>
<li><a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1148">#1148</a>[]: Add <code>Level</code> to both <code>Logger</code> and <code>SugaredLogger</code> that reports the
current minimum enabled log level.</li>
<li><a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1185">#1185</a>[]: <code>SugaredLogger</code> turns errors to zap.Error automatically.</li>
</ul>
<p>Thanks to <a href="https://github.com/Abirdcfly"><code>@​Abirdcfly</code></a>, <a href="https://github.com/craigpastro"><code>@​craigpastro</code></a>, <a href="https://github.com/nnnkkk7"><code>@​nnnkkk7</code></a>, and <a href="https://github.com/sashamelentyev"><code>@​sashamelentyev</code></a> for their
contributions to this release.</p>
<p><a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1148">#1148</a>: <a href="https://github-redirect.dependabot.com/uber-go/zap/pull/1148">uber-go/zap#1148</a>
<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1185">#1185</a>: <a href="https://github-redirect.dependabot.com/uber-go/zap/pull/1185">uber-go/zap#1185</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/uber-go/zap/blob/master/CHANGELOG.md">go.uber.org/zap's changelog</a>.</em></p>
<blockquote>
<h2>1.24.0 (30 Nov 2022)</h2>
<p>Enhancements:</p>
<ul>
<li><a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1148">#1148</a>[]: Add <code>Level</code> to both <code>Logger</code> and <code>SugaredLogger</code> that reports the
current minimum enabled log level.</li>
<li><a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1185">#1185</a>[]: <code>SugaredLogger</code> turns errors to zap.Error automatically.</li>
</ul>
<p>Thanks to <a href="https://github.com/Abirdcfly"><code>@​Abirdcfly</code></a>, <a href="https://github.com/craigpastro"><code>@​craigpastro</code></a>, <a href="https://github.com/nnnkkk7"><code>@​nnnkkk7</code></a>, and <a href="https://github.com/sashamelentyev"><code>@​sashamelentyev</code></a> for their
contributions to this release.</p>
<p><a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1148">#1148</a>: <a href="https://github.coml/uber-go/zap/pull/1148">https://github.coml/uber-go/zap/pull/1148</a>
<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1185">#1185</a>: <a href="https://github.coml/uber-go/zap/pull/1185">https://github.coml/uber-go/zap/pull/1185</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/uber-go/zap/commit/a55bdc32f526699c3b4cc51a2cc97e944d02fbbf"><code>a55bdc3</code></a> Release v1.24.0 (<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1208">#1208</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/ed5598a9e26d75aae01f4846ce31b3fe785c57c7"><code>ed5598a</code></a> Use ReplaceAll instead of Replace with -1 pos arg (<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1195">#1195</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/da406e36227eb650c4df4ab5a83dcedc00645ef2"><code>da406e3</code></a> Chore: Fix deprecation docs and links (<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1193">#1193</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/9b86a50a3e27e0e12ccb6b47288de27df7fd3d5b"><code>9b86a50</code></a> SugaredLogger: Turn error into zap.Error  (<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1185">#1185</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/9137e0e8425dfe68a311dc4f84908f17531c616e"><code>9137e0e</code></a> go.mod: Bump go directive to 1.19 (<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1181">#1181</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/7cabba7950dca373f2a057217620a7421ff2afcb"><code>7cabba7</code></a> Open absolute paths as files, limited Windows support (<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1159">#1159</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/7681a0abf65fb2f6474f481702922cf52d170654"><code>7681a0a</code></a> Export objectMarshalerPtr (<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1171">#1171</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/9abd14b74c15022c9e64b1bc790338eafe5e4abe"><code>9abd14b</code></a> chore: remove duplicate word in comments (<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1169">#1169</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/eae3743bc3e91db68bf977bc563263d4cb60777c"><code>eae3743</code></a> Logger, SugaredLogger: Add Level method (<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1148">#1148</a>)</li>
<li><a href="https://github.com/uber-go/zap/commit/0d6a75bccff91a3106f193c9e4e1678738a63f9d"><code>0d6a75b</code></a> tests: assert.Error/Contains =&gt; assert.ErrorContains (<a href="https://github-redirect.dependabot.com/uber-go/zap/issues/1158">#1158</a>)</li>
<li>See full diff in <a href="https://github.com/uber-go/zap/compare/v1.23.0...v1.24.0">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=go.uber.org/zap&package-manager=go_modules&previous-version=1.23.0&new-version=1.24.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/cli/command_repository_set_parameters.go b/cli/command_repository_set_parameters.go
index 95a0189f..30cc0df0 100644
--- a/cli/command_repository_set_parameters.go
+++ b/cli/command_repository_set_parameters.go
@@ -122,9 +122,58 @@ func (c *commandRepositorySetParameters) setRetentionModeParameter(ctx context.C
 	log(ctx).Infof(" - setting %v to %s.\n", desc, v)
 }
 
-func (c *commandRepositorySetParameters) run(ctx context.Context, rep repo.DirectRepositoryWriter) error {
-	var anyChange bool
+func updateRepositoryParameters(
+	ctx context.Context,
+	upgradeToEpochManager bool,
+	mp format.MutableParameters,
+	rep repo.DirectRepositoryWriter,
+	blobcfg format.BlobStorageConfiguration,
+	requiredFeatures []feature.Required,
+) error {
+	if upgradeToEpochManager {
+		log(ctx).Infof("migrating current indexes to epoch format")
+
+		if err := rep.ContentManager().PrepareUpgradeToIndexBlobManagerV1(ctx, mp.EpochParameters); err != nil {
+			return errors.Wrap(err, "error upgrading indexes")
+		}
+	}
+
+	if err := rep.FormatManager().SetParameters(ctx, mp, blobcfg, requiredFeatures); err != nil {
+		return errors.Wrap(err, "error setting parameters")
+	}
+
+	if upgradeToEpochManager {
+		if err := content.WriteLegacyIndexPoisonBlob(ctx, rep.BlobStorage()); err != nil {
+			log(ctx).Errorf("unable to write legacy index poison blob: %v", err)
+		}
+	}
+
+	return nil
+}
+
+func updateEpochParameters(mp *format.MutableParameters, anyChange, upgradeToEpochManager *bool) {
+	*anyChange = true
+
+	if !mp.EpochParameters.Enabled {
+		mp.EpochParameters = epoch.DefaultParameters()
+		mp.IndexVersion = 2
+		*upgradeToEpochManager = true
+	}
+
+	if mp.Version < format.FormatVersion2 {
+		mp.Version = format.FormatVersion2
+	}
+}
 
+func (c *commandRepositorySetParameters) disableBlobRetention(ctx context.Context, blobcfg *format.BlobStorageConfiguration, anyChange *bool) {
+	log(ctx).Infof("disabling blob retention")
+
+	blobcfg.RetentionMode = ""
+	blobcfg.RetentionPeriod = 0
+	*anyChange = true
+}
+
+func (c *commandRepositorySetParameters) run(ctx context.Context, rep repo.DirectRepositoryWriter) error {
 	mp, err := rep.FormatManager().GetMutableParameters()
 	if err != nil {
 		return errors.Wrap(err, "mutable parameters")
@@ -140,32 +189,28 @@ func (c *commandRepositorySetParameters) run(ctx context.Context, rep repo.Direc
 		return errors.Wrap(err, "unable to get required features")
 	}
 
+	anyChange := false
 	upgradeToEpochManager := false
 
 	if c.upgradeRepositoryFormat {
-		anyChange = true
+		updateEpochParameters(&mp, &anyChange, &upgradeToEpochManager)
+	}
 
-		if !mp.EpochParameters.Enabled {
-			mp.EpochParameters = epoch.DefaultParameters()
-			upgradeToEpochManager = true
-			mp.IndexVersion = 2
-		}
+	c.setSizeMBParameter(ctx, c.maxPackSizeMB, "maximum pack size", &mp.MaxPackSize, &anyChange)
 
-		if mp.Version < format.FormatVersion2 {
-			mp.Version = format.FormatVersion2
+	// prevent downgrade of index format
+	if c.indexFormatVersion != 0 && c.indexFormatVersion != mp.IndexVersion {
+		if c.indexFormatVersion > mp.IndexVersion {
+			c.setIntParameter(ctx, c.indexFormatVersion, "index format version", &mp.IndexVersion, &anyChange)
+		} else {
+			return errors.Errorf("index format version can only be upgraded")
 		}
 	}
 
-	c.setSizeMBParameter(ctx, c.maxPackSizeMB, "maximum pack size", &mp.MaxPackSize, &anyChange)
-	c.setIntParameter(ctx, c.indexFormatVersion, "index format version", &mp.IndexVersion, &anyChange)
-
 	if c.retentionMode == "none" {
 		if blobcfg.IsRetentionEnabled() {
-			log(ctx).Infof("disabling blob retention")
-
-			blobcfg.RetentionMode = ""
-			blobcfg.RetentionPeriod = 0
-			anyChange = true
+			// disable blob retention if already enabled
+			c.disableBlobRetention(ctx, &blobcfg, &anyChange)
 		}
 	} else {
 		c.setRetentionModeParameter(ctx, blob.RetentionMode(c.retentionMode), "storage backend blob retention mode", &blobcfg.RetentionMode, &anyChange)
@@ -186,22 +231,8 @@ func (c *commandRepositorySetParameters) run(ctx context.Context, rep repo.Direc
 		return errors.Errorf("no changes")
 	}
 
-	if upgradeToEpochManager {
-		log(ctx).Infof("migrating current indexes to epoch format")
-
-		if err := rep.ContentManager().PrepareUpgradeToIndexBlobManagerV1(ctx, mp.EpochParameters); err != nil {
-			return errors.Wrap(err, "error upgrading indexes")
-		}
-	}
-
-	if err := rep.FormatManager().SetParameters(ctx, mp, blobcfg, requiredFeatures); err != nil {
-		return errors.Wrap(err, "error setting parameters")
-	}
-
-	if upgradeToEpochManager {
-		if err := content.WriteLegacyIndexPoisonBlob(ctx, rep.BlobStorage()); err != nil {
-			log(ctx).Errorf("unable to write legacy index poison blob: %v", err)
-		}
+	if err := updateRepositoryParameters(ctx, upgradeToEpochManager, mp, rep, blobcfg, requiredFeatures); err != nil {
+		return errors.Wrap(err, "error updating repository parameters")
 	}
 
 	log(ctx).Infof("NOTE: Repository parameters updated, you must disconnect and re-connect all other Kopia clients.")
diff --git a/go.mod b/go.mod
index cf79b2d2..ee7a98c3 100644
--- a/go.mod
+++ b/go.mod
@@ -48,7 +48,7 @@ require (
 	github.com/zalando/go-keyring v0.2.1
 	github.com/zeebo/blake3 v0.2.3
 	go.opencensus.io v0.24.0 // indirect
-	go.uber.org/zap v1.23.0
+	go.uber.org/zap v1.24.0
 	golang.org/x/crypto v0.3.0
 	golang.org/x/mod v0.7.0
 	golang.org/x/net v0.2.0
diff --git a/go.sum b/go.sum
index 10ac76e4..2ed908b9 100644
--- a/go.sum
+++ b/go.sum
@@ -436,8 +436,8 @@ go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
 go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
 go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
-go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=
-go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY=
+go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
+go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=


Test patch:
diff --git a/cli/command_repository_set_parameters_test.go b/cli/command_repository_set_parameters_test.go
index 136785ac..87caecaf 100644
--- a/cli/command_repository_set_parameters_test.go
+++ b/cli/command_repository_set_parameters_test.go
@@ -182,6 +182,49 @@ func (s *formatSpecificTestSuite) TestRepositorySetParametersUpgrade(t *testing.
 	env.RunAndExpectSuccess(t, "index", "epoch", "list")
 }
 
+// TestRepositorySetParametersDowngrade test that a repository cannot be downgraded by using `set-parameters`.
+func (s *formatSpecificTestSuite) TestRepositorySetParametersDowngrade(t *testing.T) {
+	env := s.setupInMemoryRepo(t)
+
+	// checkStatusForVersion is a function with stanzas to check that the repository has the expected version.
+	// 	its saved into a variable to prevent repetition and enforce that nothing has changed between invocations
+	//  if `set-parameters`
+	checkStatusForVersion := func() {
+		out := env.RunAndExpectSuccess(t, "repository", "status")
+
+		// default values
+		require.Contains(t, out, "Max pack length:     21 MB")
+
+		switch s.formatVersion {
+		case format.FormatVersion1:
+			require.Contains(t, out, "Format version:      1")
+			require.Contains(t, out, "Epoch Manager:       disabled")
+			env.RunAndExpectFailure(t, "index", "epoch", "list")
+		case format.FormatVersion2:
+			require.Contains(t, out, "Format version:      2")
+			require.Contains(t, out, "Epoch Manager:       enabled")
+			env.RunAndExpectSuccess(t, "index", "epoch", "list")
+		default:
+			require.Contains(t, out, "Format version:      3")
+			require.Contains(t, out, "Epoch Manager:       enabled")
+			env.RunAndExpectSuccess(t, "index", "epoch", "list")
+		}
+	}
+
+	checkStatusForVersion()
+
+	env.RunAndExpectFailure(t, "repository", "set-parameters", "--index-version=1")
+
+	checkStatusForVersion()
+
+	// run basic check to ensure that an upgrade can still be performed as expected
+	env.RunAndExpectSuccess(t, "repository", "set-parameters", "--upgrade")
+
+	out := env.RunAndExpectSuccess(t, "repository", "status")
+	require.Contains(t, out, "Epoch Manager:       enabled")
+	require.Contains(t, out, "Index Format:        v2")
+}
+
 func (s *formatSpecificTestSuite) TestRepositorySetParametersRequiredFeatures(t *testing.T) {
 	env := s.setupInMemoryRepo(t)