diff --git a/changelog/unreleased/issue-4602 b/changelog/unreleased/issue-4602 index 3cba63876..7532bcb1e 100644 --- a/changelog/unreleased/issue-4602 +++ b/changelog/unreleased/issue-4602 @@ -1,7 +1,7 @@ -Change: Deprecate legacy index format +Change: Deprecate legacy index format and s3legacy layout Support for the legacy index format used by restic before version 0.2.0 has -been depreacted and will be removed in the next minor restic version. You can +been deprecated and will be removed in the next minor restic version. You can use `restic repair index` to update the index to the current format. It is possible to temporarily reenable support for the legacy index format by @@ -9,5 +9,15 @@ setting the environment variable `RESTIC_FEATURES=deprecate-legacy-index=false`. Note that this feature flag will be removed in the next minor restic version. +Support for the s3legacy layout used for the S3 backend before restic 0.7.0 +has been deprecated and will be removed in the next minor restic version. You +can migrate your S3 repository using `RESTIC_FEATURES=deprecate-s3-legacy-layout=false restic migrate s3_layout`. + +It is possible to temporarily reenable support for the legacy s3layout by +setting the environment variable +`RESTIC_FEATURES=deprecate-s3-legacy-layout=false`. Note that this feature flag +will be removed in the next minor restic version. + https://github.com/restic/restic/issues/4602 https://github.com/restic/restic/pull/4724 +https://github.com/restic/restic/pull/4743 diff --git a/cmd/restic/cmd_restore_integration_test.go b/cmd/restic/cmd_restore_integration_test.go index 2c7cbe1fb..806c7584b 100644 --- a/cmd/restic/cmd_restore_integration_test.go +++ b/cmd/restic/cmd_restore_integration_test.go @@ -11,6 +11,7 @@ import ( "testing" "time" + "github.com/restic/restic/internal/feature" "github.com/restic/restic/internal/filter" "github.com/restic/restic/internal/restic" rtest "github.com/restic/restic/internal/test" @@ -274,6 +275,7 @@ func TestRestoreNoMetadataOnIgnoredIntermediateDirs(t *testing.T) { } func TestRestoreLocalLayout(t *testing.T) { + defer feature.TestSetFlag(t, feature.Flag, feature.DeprecateS3LegacyLayout, false)() env, cleanup := withTestEnvironment(t) defer cleanup() diff --git a/internal/backend/layout/layout.go b/internal/backend/layout/layout.go index b600566a4..052fd66ca 100644 --- a/internal/backend/layout/layout.go +++ b/internal/backend/layout/layout.go @@ -10,6 +10,7 @@ import ( "github.com/restic/restic/internal/backend" "github.com/restic/restic/internal/debug" "github.com/restic/restic/internal/errors" + "github.com/restic/restic/internal/feature" "github.com/restic/restic/internal/fs" "github.com/restic/restic/internal/restic" ) @@ -93,6 +94,8 @@ func hasBackendFile(ctx context.Context, fs Filesystem, dir string) (bool, error // cannot be detected automatically. var ErrLayoutDetectionFailed = errors.New("auto-detecting the filesystem layout failed") +var ErrLegacyLayoutFound = errors.New("detected legacy S3 layout. Use `RESTIC_FEATURES=deprecate-s3-legacy-layout=false restic migrate s3_layout` to migrate your repository") + // DetectLayout tries to find out which layout is used in a local (or sftp) // filesystem at the given path. If repo is nil, an instance of LocalFilesystem // is used. @@ -123,6 +126,10 @@ func DetectLayout(ctx context.Context, repo Filesystem, dir string) (Layout, err } if foundKeyFile && !foundKeysFile { + if feature.Flag.Enabled(feature.DeprecateS3LegacyLayout) { + return nil, ErrLegacyLayoutFound + } + debug.Log("found s3 layout at %v", dir) return &S3LegacyLayout{ Path: dir, @@ -145,6 +152,10 @@ func ParseLayout(ctx context.Context, repo Filesystem, layout, defaultLayout, pa Join: repo.Join, } case "s3legacy": + if feature.Flag.Enabled(feature.DeprecateS3LegacyLayout) { + return nil, ErrLegacyLayoutFound + } + l = &S3LegacyLayout{ Path: path, Join: repo.Join, diff --git a/internal/backend/layout/layout_test.go b/internal/backend/layout/layout_test.go index 998f5aeb6..55a0749c9 100644 --- a/internal/backend/layout/layout_test.go +++ b/internal/backend/layout/layout_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/restic/restic/internal/backend" + "github.com/restic/restic/internal/feature" rtest "github.com/restic/restic/internal/test" ) @@ -352,6 +353,7 @@ func TestS3LegacyLayout(t *testing.T) { } func TestDetectLayout(t *testing.T) { + defer feature.TestSetFlag(t, feature.Flag, feature.DeprecateS3LegacyLayout, false)() path := rtest.TempDir(t) var tests = []struct { @@ -389,6 +391,7 @@ func TestDetectLayout(t *testing.T) { } func TestParseLayout(t *testing.T) { + defer feature.TestSetFlag(t, feature.Flag, feature.DeprecateS3LegacyLayout, false)() path := rtest.TempDir(t) var tests = []struct { diff --git a/internal/backend/local/config.go b/internal/backend/local/config.go index dc5e7948c..e08f05550 100644 --- a/internal/backend/local/config.go +++ b/internal/backend/local/config.go @@ -10,7 +10,7 @@ import ( // Config holds all information needed to open a local repository. type Config struct { Path string - Layout string `option:"layout" help:"use this backend directory layout (default: auto-detect)"` + Layout string `option:"layout" help:"use this backend directory layout (default: auto-detect) (deprecated)"` Connections uint `option:"connections" help:"set a limit for the number of concurrent operations (default: 2)"` } diff --git a/internal/backend/local/layout_test.go b/internal/backend/local/layout_test.go index 46f3996bb..00c91376a 100644 --- a/internal/backend/local/layout_test.go +++ b/internal/backend/local/layout_test.go @@ -6,10 +6,12 @@ import ( "testing" "github.com/restic/restic/internal/backend" + "github.com/restic/restic/internal/feature" rtest "github.com/restic/restic/internal/test" ) func TestLayout(t *testing.T) { + defer feature.TestSetFlag(t, feature.Flag, feature.DeprecateS3LegacyLayout, false)() path := rtest.TempDir(t) var tests = []struct { diff --git a/internal/backend/s3/config.go b/internal/backend/s3/config.go index b4d44399f..4aea4c3d1 100644 --- a/internal/backend/s3/config.go +++ b/internal/backend/s3/config.go @@ -20,7 +20,7 @@ type Config struct { Secret options.SecretString Bucket string Prefix string - Layout string `option:"layout" help:"use this backend layout (default: auto-detect)"` + Layout string `option:"layout" help:"use this backend layout (default: auto-detect) (deprecated)"` StorageClass string `option:"storage-class" help:"set S3 storage class (STANDARD, STANDARD_IA, ONEZONE_IA, INTELLIGENT_TIERING or REDUCED_REDUNDANCY)"` Connections uint `option:"connections" help:"set a limit for the number of concurrent connections (default: 5)"` diff --git a/internal/backend/sftp/config.go b/internal/backend/sftp/config.go index 65af50d19..aa8ac7bff 100644 --- a/internal/backend/sftp/config.go +++ b/internal/backend/sftp/config.go @@ -13,7 +13,7 @@ import ( type Config struct { User, Host, Port, Path string - Layout string `option:"layout" help:"use this backend directory layout (default: auto-detect)"` + Layout string `option:"layout" help:"use this backend directory layout (default: auto-detect) (deprecated)"` Command string `option:"command" help:"specify command to create sftp connection"` Args string `option:"args" help:"specify arguments for ssh"` diff --git a/internal/backend/sftp/layout_test.go b/internal/backend/sftp/layout_test.go index 9cf24a753..8bb7eac01 100644 --- a/internal/backend/sftp/layout_test.go +++ b/internal/backend/sftp/layout_test.go @@ -8,6 +8,7 @@ import ( "github.com/restic/restic/internal/backend" "github.com/restic/restic/internal/backend/sftp" + "github.com/restic/restic/internal/feature" rtest "github.com/restic/restic/internal/test" ) @@ -16,6 +17,7 @@ func TestLayout(t *testing.T) { t.Skip("sftp server binary not available") } + defer feature.TestSetFlag(t, feature.Flag, feature.DeprecateS3LegacyLayout, false)() path := rtest.TempDir(t) var tests = []struct { diff --git a/internal/feature/registry.go b/internal/feature/registry.go index 4693b8909..2d2e45edf 100644 --- a/internal/feature/registry.go +++ b/internal/feature/registry.go @@ -5,13 +5,15 @@ var Flag = New() // flag names are written in kebab-case const ( - DeprecateLegacyIndex FlagName = "deprecate-legacy-index" - DeviceIDForHardlinks FlagName = "device-id-for-hardlinks" + DeprecateLegacyIndex FlagName = "deprecate-legacy-index" + DeprecateS3LegacyLayout FlagName = "deprecate-s3-legacy-layout" + DeviceIDForHardlinks FlagName = "device-id-for-hardlinks" ) func init() { Flag.SetFlags(map[FlagName]FlagDesc{ - DeprecateLegacyIndex: {Type: Beta, Description: "disable support for index format used by restic 0.1.0. Use `restic repair index` to update the index if necessary."}, - DeviceIDForHardlinks: {Type: Alpha, Description: "store deviceID only for hardlinks to reduce metadata changes for example when using btrfs subvolumes. Will be removed in a future restic version after repository format 3 is available"}, + DeprecateLegacyIndex: {Type: Beta, Description: "disable support for index format used by restic 0.1.0. Use `restic repair index` to update the index if necessary."}, + DeprecateS3LegacyLayout: {Type: Beta, Description: "disable support for S3 legacy layout used up to restic 0.7.0. Use `RESTIC_FEATURES=deprecate-s3-legacy-layout=false restic migrate s3_layout` to migrate your S3 repository if necessary."}, + DeviceIDForHardlinks: {Type: Alpha, Description: "store deviceID only for hardlinks to reduce metadata changes for example when using btrfs subvolumes. Will be removed in a future restic version after repository format 3 is available"}, }) }