mirror of
https://github.com/restic/restic.git
synced 2024-12-25 01:06:39 +00:00
Merge pull request #1209 from restic/handle-colliding-names
Resolve name collisions
This commit is contained in:
commit
5dfb4d1195
3 changed files with 74 additions and 1 deletions
|
@ -30,6 +30,10 @@ Important Changes in 0.X.Y
|
||||||
included) in a restore, they are not loaded from the repo any more.
|
included) in a restore, they are not loaded from the repo any more.
|
||||||
https://github.com/restic/restic/pull/1044
|
https://github.com/restic/restic/pull/1044
|
||||||
|
|
||||||
|
* Name collisions are now resolved by appending a counter.
|
||||||
|
https://github.com/restic/restic/issues/1179
|
||||||
|
https://github.com/restic/restic/pull/1209
|
||||||
|
|
||||||
|
|
||||||
Small changes
|
Small changes
|
||||||
-------------
|
-------------
|
||||||
|
|
|
@ -383,7 +383,22 @@ func (arch *Archiver) dirWorker(ctx context.Context, wg *sync.WaitGroup, p *rest
|
||||||
panic("invalid null subtree restic.ID")
|
panic("invalid null subtree restic.ID")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tree.Insert(node)
|
|
||||||
|
// insert node into tree, resolve name collisions
|
||||||
|
name := node.Name
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
i++
|
||||||
|
err := tree.Insert(node)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
newName := fmt.Sprintf("%v-%d", name, i)
|
||||||
|
fmt.Fprintf(os.Stderr, "%v: name collision for %q, renaming to %q\n", filepath.Dir(node.Path), node.Name, newName)
|
||||||
|
node.Name = newName
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
node := &restic.Node{}
|
node := &restic.Node{}
|
||||||
|
|
|
@ -4,6 +4,9 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -312,3 +315,54 @@ func TestArchiveEmptySnapshot(t *testing.T) {
|
||||||
t.Errorf("expected null snapshot for empty snapshot, got %v", sn)
|
t.Errorf("expected null snapshot for empty snapshot, got %v", sn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func chdir(t testing.TB, target string) (cleanup func()) {
|
||||||
|
curdir, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("chdir to %v", target)
|
||||||
|
err = os.Chdir(target)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return func() {
|
||||||
|
t.Logf("chdir back to %v", curdir)
|
||||||
|
err := os.Chdir(curdir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestArchiveNameCollision(t *testing.T) {
|
||||||
|
repo, cleanup := repository.TestRepository(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
dir, cleanup := TempDir(t)
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
root := filepath.Join(dir, "root")
|
||||||
|
OK(t, os.MkdirAll(root, 0755))
|
||||||
|
|
||||||
|
OK(t, ioutil.WriteFile(filepath.Join(dir, "testfile"), []byte("testfile1"), 0644))
|
||||||
|
OK(t, ioutil.WriteFile(filepath.Join(dir, "root", "testfile"), []byte("testfile2"), 0644))
|
||||||
|
|
||||||
|
defer chdir(t, root)()
|
||||||
|
|
||||||
|
arch := archiver.New(repo)
|
||||||
|
|
||||||
|
sn, id, err := arch.Snapshot(context.TODO(), nil, []string{"testfile", filepath.Join("..", "testfile")}, nil, "localhost", nil)
|
||||||
|
OK(t, err)
|
||||||
|
|
||||||
|
t.Logf("snapshot archived as %v", id)
|
||||||
|
|
||||||
|
tree, err := repo.LoadTree(context.TODO(), *sn.Tree)
|
||||||
|
OK(t, err)
|
||||||
|
|
||||||
|
if len(tree.Nodes) != 2 {
|
||||||
|
t.Fatalf("tree has %d nodes, wanted 2: %v", len(tree.Nodes), tree.Nodes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue