diff --git a/CHANGELOG.md b/CHANGELOG.md index cea2f9987..ff6fa094c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -707,7 +707,7 @@ restic users. The changes are ordered by importance. correctly. Specifying volume names is now handled correctly. To restore snapshots created - before this bugfix, use the : syntax. For example, to restore + before this bugfix, use the : syntax. For example, to restore a snapshot with ID `12345678` that backed up `C:`, use the following command: ``` diff --git a/changelog/0.17.1_2024-09-05/issue-2004 b/changelog/0.17.1_2024-09-05/issue-2004 index 5372eeb8c..70d17663b 100644 --- a/changelog/0.17.1_2024-09-05/issue-2004 +++ b/changelog/0.17.1_2024-09-05/issue-2004 @@ -6,7 +6,7 @@ resulting snapshot would result in an error. Note that using `C:\` as backup target worked correctly. Specifying volume names is now handled correctly. To restore snapshots -created before this bugfix, use the : syntax. For +created before this bugfix, use the : syntax. For example, to restore a snapshot with ID `12345678` that backed up `C:`, use the following command: diff --git a/cmd/restic/cmd_diff.go b/cmd/restic/cmd_diff.go index 30b0878c0..500e38ff5 100644 --- a/cmd/restic/cmd_diff.go +++ b/cmd/restic/cmd_diff.go @@ -39,7 +39,7 @@ Metadata comparison will likely not work if a backup was created using the To only compare files in specific subfolders, you can use the "snapshotID:subfolder" syntax, where "subfolder" is a path within the -snapshot. +snapshot tree as shown by "restic ls". EXIT STATUS =========== diff --git a/cmd/restic/cmd_dump.go b/cmd/restic/cmd_dump.go index 20904b43c..87ca88f2c 100644 --- a/cmd/restic/cmd_dump.go +++ b/cmd/restic/cmd_dump.go @@ -35,7 +35,7 @@ repository. To include the folder content at the root of the archive, you can use the "snapshotID:subfolder" syntax, where "subfolder" is a path within the -snapshot. +snapshot tree as shown by "restic ls". EXIT STATUS =========== diff --git a/cmd/restic/cmd_restore.go b/cmd/restic/cmd_restore.go index 76a0044da..d797d1b68 100644 --- a/cmd/restic/cmd_restore.go +++ b/cmd/restic/cmd_restore.go @@ -34,7 +34,8 @@ The special snapshotID "latest" can be used to restore the latest snapshot in th repository. To only restore a specific subfolder, you can use the "snapshotID:subfolder" -syntax, where "subfolder" is a path within the snapshot. +syntax, where "subfolder" is a path within the snapshot tree as shown by +"restic ls". POSIX ACLs are always restored by their numeric value, while file ownership can optionally be restored by name instead of numeric value. diff --git a/doc/040_backup.rst b/doc/040_backup.rst index 446af6fd0..c34670d19 100644 --- a/doc/040_backup.rst +++ b/doc/040_backup.rst @@ -609,8 +609,8 @@ and displays a small statistic, just pass the command two snapshot IDs: To only compare files in specific subfolders, you can use the ``:`` syntax, where ``snapshot`` is the ID of a snapshot (or the string ``latest``) and ``subfolder`` -is a path within the snapshot. For example, to only compare files in the ``/restic`` -folder, you could use the following command: +is a path within the snapshot tree as shown by ``restic ls``. For example, to only compare files in +the ``/restic`` folder, you could use the following command: .. code-block:: console diff --git a/doc/050_restore.rst b/doc/050_restore.rst index 6cf2f0145..ec88d55c0 100644 --- a/doc/050_restore.rst +++ b/doc/050_restore.rst @@ -54,10 +54,10 @@ This will restore the file to ``/tmp/restore/home/user/work/foo``. To only restore a specific subfolder, you can use the ``:`` syntax, where ``snapshot`` is the ID of a snapshot (or the string ``latest``) -and ``subfolder`` is a path within the snapshot. Note that the subfolder syntax -also affects options like ``--include`` and ``--exclude``, such that their -arguments should be specified relative to ``subfolder`` (e.g. ``/foo`` instead -of ``/home/user/work/foo``). +and ``subfolder`` is a path within the snapshot tree as shown by ``restic ls``. +Note that the subfolder syntax also affects options like ``--include`` and +``--exclude``, such that their arguments should be specified relative to +``subfolder`` (e.g. ``/foo`` instead of ``/home/user/work/foo``). .. code-block:: console diff --git a/internal/data/tree.go b/internal/data/tree.go index 76c548cf9..e137dfef2 100644 --- a/internal/data/tree.go +++ b/internal/data/tree.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "runtime" "io" "iter" @@ -311,6 +312,9 @@ func FindTreeDirectory(ctx context.Context, repo restic.BlobLoader, id *restic.I return nil, fmt.Errorf("path %s: %w", subfolder, err) } if node == nil { + if runtime.GOOS == "windows" && strings.Contains(dir, "\\") { + return nil, fmt.Errorf("path %s: not found; subfolder syntax currently requires forward slashes; check the output of `restic ls` for valid paths", subfolder) + } return nil, fmt.Errorf("path %s: not found", subfolder) } if node.Type != NodeTypeDir || node.Subtree == nil { diff --git a/internal/data/tree_test.go b/internal/data/tree_test.go index 47fc4b9a0..d8f0207e8 100644 --- a/internal/data/tree_test.go +++ b/internal/data/tree_test.go @@ -7,6 +7,7 @@ import ( "fmt" "os" "path/filepath" + "runtime" "slices" "strconv" "strings" @@ -401,6 +402,22 @@ func TestFindTreeDirectory(t *testing.T) { rtest.Assert(t, err != nil, "missing error on null tree id") } +func TestFindTreeDirectoryWindowsBackslashHint(t *testing.T) { + repo := repository.TestRepository(t) + sn := data.TestCreateSnapshot(t, repo, parseTimeUTC("2017-07-07 07:07:08"), 1) + + _, err := data.FindTreeDirectory(context.TODO(), repo, sn.Tree, `missing\path`) + rtest.Assert(t, err != nil, "expected error") + + if runtime.GOOS == "windows" { + rtest.Assert(t, strings.Contains(err.Error(), "forward slashes"), + "expected backslash hint on Windows, got %v", err) + } else { + rtest.Assert(t, err.Error() == `path missing\path: not found`, + "unexpected err: %v", err) + } +} + func TestDualTreeIterator(t *testing.T) { testErr := errors.New("test error")