func DoTestPatchRenameFileSameDir(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("baz", tg.B(42, 65537))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) assert.Equal(t, 1, len(patchPlan.Cmds)) rename, isRename := patchPlan.Cmds[0].(*Transfer) assert.T(t, isRename) assert.T(t, strings.HasSuffix(rename.From.Resolve(), filepath.Join("foo", "baz"))) assert.T(t, strings.HasSuffix(rename.To.Resolve(), filepath.Join("foo", "bar"))) }
func DoTestPatchIdentity(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) assert.Equal(t, "1b1979b8746948cedc81488e92d1ad715e38bbfc", srcStore.Repo().Root().(fs.Dir).Info().Strong) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) assert.Equal(t, "1b1979b8746948cedc81488e92d1ad715e38bbfc", dstStore.Repo().Root().(fs.Dir).Info().Strong) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) assert.T(t, len(patchPlan.Cmds) > 0) for i := 0; i < len(patchPlan.Cmds); i++ { keep := patchPlan.Cmds[0].(*Keep) assert.T(t, strings.HasPrefix(dstpath, keep.Path.Resolve())) } }
func DoTestPatchFileAppend(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537), tg.B(43, 65537))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("bar", tg.B(42, 65537))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) complete := false for i, cmd := range patchPlan.Cmds { switch { case i == 0: localTemp, isTemp := cmd.(*LocalTemp) assert.T(t, isTemp) assert.Equal(t, filepath.Join(dstpath, "foo", "bar"), localTemp.Path.Resolve()) case i >= 1 && i <= 8: ltc, isLtc := cmd.(*LocalTempCopy) assert.Tf(t, isLtc, "cmd %d", i) assert.Equal(t, ltc.LocalOffset, ltc.TempOffset) assert.Equal(t, int64(fs.BLOCKSIZE), ltc.Length) assert.Equal(t, int64(0), ltc.LocalOffset%int64(fs.BLOCKSIZE)) case i == 9: stc, isStc := cmd.(*SrcTempCopy) assert.T(t, isStc) assert.Equal(t, int64(65538), stc.Length) case i == 10: _, isRwt := cmd.(*ReplaceWithTemp) assert.T(t, isRwt) complete = true case i > 10: t.Fatalf("too many commands") } } assert.T(t, complete, "missing expected number of commands") failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) srcRoot, errors := fs.IndexDir(srcpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) dstRoot, errors := fs.IndexDir(dstpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) assert.Equal(t, srcRoot.Info().Strong, dstRoot.Info().Strong) }
func DoTestPatchAdd(t *testing.T, mkrepo repoMaker) { tg := treegen.New() files := []treegen.Generated{} for i := 0; i < 10; i++ { files = append(files, tg.F("", tg.B(int64(42*i), int64(500000*i)))) } treeSpec := tg.D("foo", tg.D("bar", files...)) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(filepath.Join(srcpath, "foo"), srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.D("bar"), tg.D("baz")) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(filepath.Join(dstpath, "foo"), dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) for _, cmd := range patchPlan.Cmds { _, isSfd := cmd.(*SrcFileDownload) assert.T(t, isSfd) } }
func TestPatchPreserveKeeps(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(6806, 65536)), tg.F("blop", tg.B(6806, 65536))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("baz", tg.B(6806, 65536)), tg.F("blop", tg.B(6806, 65536))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) info, err := os.Stat(filepath.Join(dstpath, "foo", "bar")) assert.T(t, err == nil && info != nil) info, err = os.Stat(filepath.Join(dstpath, "foo", "blop")) assert.T(t, err == nil && info != nil) }
func TestPatchRenameScope(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(6806, 65536)), tg.F("baz", tg.B(6806, 65536))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("baz", tg.B(6806, 65536)), tg.F("blop", tg.B(6806, 65536))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) srcDir, err := fs.IndexDir(srcpath) assert.T(t, err == nil) dstDir, err := fs.IndexDir(dstpath) assert.T(t, err == nil) assert.Equal(t, srcDir.Strong(), dstDir.Strong()) }
func DoTestPatchDepConflict(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("gloo", tg.F("bloo", tg.B(99, 8192), tg.B(100, 10000)), tg.D("groo", tg.D("snoo", tg.F("bar", tg.B(42, 65537)))))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("gloo", tg.B(99, 10000))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) assertNoRelocs(t, dstpath) }
func TestClean(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("bar", tg.D("aleph", tg.F("A", tg.B(42, 65537)), tg.F("a", tg.B(42, 65537))))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.D("bar", tg.D("aleph", tg.F("A", tg.B(42, 65537)), tg.F("a", tg.B(42, 65537))), tg.D("beth", tg.F("B", tg.B(43, 65537)), tg.F("b", tg.B(43, 65537))), tg.D("jimmy", tg.F("G", tg.B(44, 65537)), tg.F("g", tg.B(44, 65537)))), tg.D("baz", tg.D("uno", tg.F("1", tg.B(1, 65537)), tg.F("I", tg.B(1, 65537))), tg.D("dos", tg.F("2", tg.B(11, 65537)), tg.F("II", tg.B(11, 65537))), tg.D("tres", tg.F("3", tg.B(111, 65537)), tg.F("III", tg.B(111, 65537))))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) onePath := dstStore.Resolve(filepath.Join("foo", "baz", "uno", "1")) _, err = os.Stat(onePath) assert.Tf(t, err == nil, "%v", err) patchPlan := NewPatchPlan(srcStore, dstStore) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil, "%v", failedCmd) assert.Tf(t, err == nil, "%v", err) errors := make(chan error, 10) patchPlan.Clean(errors) close(errors) for err := range errors { assert.Tf(t, err == nil, "%v", err) } onePath = dstStore.Resolve(filepath.Join("foo", "baz", "uno", "1")) _, err = os.Stat(onePath) assert.Tf(t, err != nil, "%v", err) }
func DoTestSetModeNew(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("bar", tg.D("aleph", tg.F("A", tg.B(42, 65537)), tg.F("a", tg.B(42, 65537))))) srcpath := treegen.TestTree(t, treeSpec) os.Chmod(filepath.Join(srcpath, "foo", "bar", "aleph", "A"), 0765) os.Chmod(filepath.Join(srcpath, "foo", "bar"), 0711) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo") dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil, "%v", failedCmd) assert.Tf(t, err == nil, "%v", err) errors := make(chan os.Error) go func() { patchPlan.Clean(errors) close(errors) }() for err := range errors { assert.Tf(t, err == nil, "%v", err) } errors = make(chan os.Error) go func() { patchPlan.SetMode(errors) close(errors) }() for err := range errors { assert.Tf(t, err == nil, "%v", err) } fileinfo, err := os.Stat(filepath.Join(dstpath, "foo", "bar", "aleph", "A")) assert.T(t, fileinfo != nil) assert.Equal(t, uint32(0765), fileinfo.Permission()) fileinfo, err = os.Stat(filepath.Join(dstpath, "foo", "bar")) assert.T(t, fileinfo != nil) assert.Equal(t, uint32(0711), fileinfo.Permission()) }
func DoTestPatchRelocConflict(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("gloo", tg.F("bloo", tg.B(99, 99)), tg.D("groo", tg.D("snoo", tg.F("bar", tg.B(42, 65537)))))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("gloo", tg.B(99, 99))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) assert.Equal(t, 3, len(patchPlan.Cmds)) for i, cmd := range patchPlan.Cmds { switch i { case 0: conflict, is := cmd.(*Conflict) assert.T(t, is) assert.T(t, strings.HasSuffix(conflict.Path.RelPath, filepath.Join("foo", "gloo"))) case 1: copy, is := cmd.(*Transfer) assert.T(t, is) assert.T(t, strings.HasSuffix(copy.From.Resolve(), filepath.Join("foo", "gloo"))) assert.T(t, strings.HasSuffix(copy.To.Resolve(), filepath.Join("foo", "gloo", "bloo"))) case 2: copy, is := cmd.(*SrcFileDownload) assert.T(t, is) assert.Equal(t, "764b5f659f70e69d4a87fe6ed138af40be36c514", copy.SrcFile.Info().Strong) } } failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) assertNoRelocs(t, dstpath) }
func DoTestPatchRenameScope(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(6806, 65536)), tg.F("baz", tg.B(6806, 65536))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("baz", tg.B(6806, 65536)), tg.F("blop", tg.B(6806, 65536))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) // The actual content of dst after the patch depends on // which file the repo chooses when matching foo/bar // to baz or blop in dst. // // If blop matches, it will get renamed to bar and the trees will // become identical. However if baz matches, blop will be left in place. srcDir, errors := fs.IndexDir(srcpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) dstDir, errors := fs.IndexDir(dstpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) for _, path := range []string{"foo/bar", "foo/baz"} { srcNode, has := fs.Lookup(srcDir, path) assert.T(t, has) dstNode, has := fs.Lookup(dstDir, path) assert.T(t, has) assert.Equal(t, srcNode.(fs.File).Info().Strong, dstNode.(fs.File).Info().Strong) } }
func Patch(src string, dst string) (*PatchPlan, os.Error) { srcStore, err := fs.NewLocalStore(src, fs.NewMemRepo()) if err != nil { return nil, err } dstStore, err := fs.NewLocalStore(dst, fs.NewMemRepo()) if err != nil { return nil, err } return NewPatchPlan(srcStore, dstStore), nil }
// Test the patch planner on a case where the source file is a shorter, // truncated version of the destination. // Execute the patch plan and check both resulting trees are identical. func TestPatchFileTruncate(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("bar", tg.B(42, 65537), tg.B(43, 65537))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) complete := false for i, cmd := range patchPlan.Cmds { switch { case i == 0: localTemp, isTemp := cmd.(*LocalTemp) assert.T(t, isTemp) assert.Equal(t, filepath.Join(dstpath, "foo", "bar"), localTemp.Path.Resolve()) case i >= 1 && i <= 8: ltc, isLtc := cmd.(*LocalTempCopy) assert.Tf(t, isLtc, "cmd %d", i) assert.Equal(t, ltc.LocalOffset, ltc.TempOffset) assert.Equal(t, int64(fs.BLOCKSIZE), ltc.Length) assert.Equal(t, int64(0), ltc.LocalOffset%int64(fs.BLOCKSIZE)) case i == 9: stc, isStc := cmd.(*SrcTempCopy) assert.T(t, isStc) assert.Equal(t, int64(1), stc.Length) complete = true case i > 10: t.Fatalf("too many commands") } } assert.T(t, complete, "missing expected number of commands") failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) srcRoot, _ := fs.IndexDir(srcpath) dstRoot, _ := fs.IndexDir(dstpath) assert.Equal(t, srcRoot.Strong(), dstRoot.Strong()) }
func DoTestStoreRelPath(t *testing.T, repo fs.NodeRepo) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) path := treegen.TestTree(t, treeSpec) defer os.RemoveAll(path) store, err := fs.NewLocalStore(path, repo) assert.T(t, err == nil) relFoo := store.RelPath(filepath.Join(path, "foo")) assert.Equalf(t, "foo", relFoo, "'%v': not a foo", relFoo) // Relocate bar newBar, err := store.Relocate(filepath.Join(filepath.Join(path, "foo"), "bar")) assert.T(t, err == nil) // new bar's parent should still be foo newBarParent, _ := filepath.Split(newBar) newBarParent = strings.TrimRight(newBarParent, "/\\") // old bar should not exist _, err = os.Stat(filepath.Join(filepath.Join(path, "foo"), "bar")) assert.T(t, err != nil) foobar := filepath.Join("foo", "bar") assert.Equal(t, newBar, store.Resolve(foobar), "reloc path %s != resolve foo/bar %s", newBar, store.Resolve(foobar)) }
// Test patch planner on case where the source and // destination have a direct conflict in structure. // A path in the source is a directory, path in destination // already contains a file at that location. func TestPatchSimpleDirFileConflict(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("gloo", tg.F("bloo", tg.B(99, 99)), tg.D("groo", tg.D("snoo", tg.F("bar", tg.B(42, 65537)))))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("gloo", tg.B(99, 999))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) assert.Equal(t, 3, len(patchPlan.Cmds)) for i, cmd := range patchPlan.Cmds { switch i { case 0: conflict, is := cmd.(*Conflict) assert.T(t, is) assert.T(t, strings.HasSuffix(conflict.Path.RelPath, filepath.Join("foo", "gloo"))) case 1: copy, is := cmd.(*SrcFileDownload) assert.T(t, is) assert.Equal(t, "beced72da0cf22301e23bdccec61bf9763effd6f", copy.SrcFile.Strong()) case 2: copy, is := cmd.(*SrcFileDownload) assert.T(t, is) assert.Equal(t, "764b5f659f70e69d4a87fe6ed138af40be36c514", copy.SrcFile.Strong()) } } }
func DoTestPatchWeakCollision(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(6806, 65536))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("bar", tg.B(9869, 65536))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) // Src and dst blocks have same weak checksum assert.Equal(t, (srcStore.Repo().Root().(fs.Dir)).SubDirs()[0].Files()[0].Blocks()[0].Info().Weak, (dstStore.Repo().Root().(fs.Dir)).SubDirs()[0].Files()[0].Blocks()[0].Info().Weak) // Src and dst blocks have different strong checksum srcRoot := srcStore.Repo().Root().(fs.Dir) dstRoot := dstStore.Repo().Root().(fs.Dir) assert.Tf(t, srcRoot.Info().Strong != dstRoot.Info().Strong, "wtf: %v == %v", srcRoot.Info().Strong, dstRoot.Info().Strong) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) srcDir, errors := fs.IndexDir(srcpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) dstDir, errors := fs.IndexDir(dstpath, fs.NewMemRepo()) assert.Equalf(t, 0, len(errors), "%v", errors) assert.Equal(t, srcDir.Info().Strong, dstDir.Info().Strong) }
func Serve(path string) (*StoreSrv, os.Error) { store, err := fs.NewLocalStore(path) if err != nil { return nil, err } return NewStoreSrv(store) }
func DoTestPatchRenameFileDifferentDir(t *testing.T, mkrepo repoMaker) { tg := treegen.New() treeSpec := tg.D("foo", tg.D("gloo", tg.F("bloo", tg.B(99, 99)), tg.D("groo", tg.D("snoo", tg.F("bar", tg.B(42, 65537)))))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcRepo := mkrepo(t) defer srcRepo.Close() srcStore, err := fs.NewLocalStore(srcpath, srcRepo) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("pancake", tg.F("butter", tg.B(42, 65537)), tg.F("syrup", tg.B(99, 99))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstRepo := mkrepo(t) defer dstRepo.Close() dstStore, err := fs.NewLocalStore(dstpath, dstRepo) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) assert.Equal(t, 2, len(patchPlan.Cmds)) for i := 0; i < len(patchPlan.Cmds); i++ { _, isRename := patchPlan.Cmds[0].(*Transfer) assert.T(t, isRename) } // Now flip patchPlan = NewPatchPlan(dstStore, srcStore) assert.Equal(t, 2, len(patchPlan.Cmds)) for i := 0; i < len(patchPlan.Cmds); i++ { _, isRename := patchPlan.Cmds[0].(*Transfer) assert.T(t, isRename) } }
func main() { verboseOpt := optarg.NewBoolOption("v", "verbose") files, err := optarg.Parse() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) optarg.Usage() os.Exit(1) } if len(files) < 2 { fmt.Printf("Usage: %s <src> <dst>\n", os.Args[0]) os.Exit(1) } srcpath := files[0] dstpath := files[1] srcStore, err := fs.NewLocalStore(srcpath) if err != nil { die(fmt.Sprintf("Failed to read source %s", srcpath), err) } dstStore, err := fs.NewLocalStore(dstpath) if err != nil { die(fmt.Sprintf("Failed to read destination %s", srcpath), err) } patchPlan := sync.NewPatchPlan(srcStore, dstStore) if verboseOpt.Value { fmt.Printf("%v\n", patchPlan) } failedCmd, err := patchPlan.Exec() if err != nil { die(failedCmd.String(), err) } os.Exit(0) }
func TestPatchWeakCollision(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(6806, 65536))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) tg = treegen.New() treeSpec = tg.D("foo", tg.F("bar", tg.B(9869, 65536))) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) // Src and dst blocks have same weak checksum assert.Equal(t, srcStore.Root().SubDirs[0].Files[0].Blocks[0].Weak(), dstStore.Root().SubDirs[0].Files[0].Blocks[0].Weak()) // Src and dst blocks have different strong checksum assert.Tf(t, srcStore.Root().Strong() != dstStore.Root().Strong(), "wtf: %v == %v", srcStore.Root().Strong(), dstStore.Root().Strong()) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) failedCmd, err := patchPlan.Exec() assert.Tf(t, failedCmd == nil && err == nil, "%v: %v", failedCmd, err) srcDir, err := fs.IndexDir(srcpath) assert.T(t, err == nil) dstDir, err := fs.IndexDir(dstpath) assert.T(t, err == nil) assert.Equal(t, srcDir.Strong(), dstDir.Strong()) }
// Test the patch planner on two identical directory structures. func TestPatchIdentity(t *testing.T) { tg := treegen.New() treeSpec := tg.D("foo", tg.F("bar", tg.B(42, 65537))) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) srcStore, err := fs.NewLocalStore(srcpath) assert.T(t, err == nil) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) dstStore, err := fs.NewLocalStore(dstpath) assert.T(t, err == nil) patchPlan := NewPatchPlan(srcStore, dstStore) // printPlan(patchPlan) assert.T(t, len(patchPlan.Cmds) > 0) for i := 0; i < len(patchPlan.Cmds); i++ { keep := patchPlan.Cmds[0].(*Keep) assert.T(t, strings.HasPrefix(dstpath, keep.Path.Resolve())) } }
func main() { if len(os.Args) < 2 { fmt.Fprintf(os.Stderr, "Usage: %s <path>\n", os.Args[0]) os.Exit(1) } local, err := fs.NewLocalStore(os.Args[1]) if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err.String()) os.Exit(1) } var router = new(mux.Router) router.HandleFunc(fmt.Sprintf("/%s", web.NODEROOT), srv.TreeHandler(local)) router.HandleFunc(fmt.Sprintf("/%s/{strong}", web.BLOCKS), srv.BlockHandler(local)) router.HandleFunc(fmt.Sprintf("/%s/{strong}/{offset}/{length}", web.FILES), srv.FileHandler(local)) http.Handle("/", router) http.ListenAndServe(":8080", nil) }
func main() { if len(os.Args) < 2 { fmt.Printf("Usage: %s <path>\n", os.Args[0]) os.Exit(1) } path := os.Args[1] store, err := fs.NewLocalStore(path) if err != nil { die(fmt.Sprintf("Failed to read source %s", path), err) } srv, err := srv.NewStoreSrv(store) if err != nil { die("Failed to create server", err) } srv.Start(srv) err = srv.StartNetListener("tcp", ":5640") if err != nil { die("Failed to start server", err) } }
func main() { verboseOpt := optarg.NewBoolOption("v", "verbose") files, err := optarg.Parse() if err != nil { fmt.Fprintf(os.Stderr, "%s\n", err) optarg.Usage() os.Exit(1) } if len(files) < 2 { die(fmt.Sprintf("Usage: %s <src> <dst>", os.Args[0]), nil) } srcpath := files[0] dstpath := files[1] srcinfo, err := os.Stat(srcpath) if err != nil { die(fmt.Sprintf("Cannot read <src> %s:", srcpath), err) } dstinfo, err := os.Stat(dstpath) if err == os.EEXIST && srcinfo.IsDirectory() { os.MkdirAll(dstpath, 0755) } else if err == nil && srcinfo.IsDirectory() != dstinfo.IsDirectory() { die(fmt.Sprintf( "Cannot sync %s to %s: one of these things is not like the other", srcinfo, dstinfo), nil) } srcDbF, err := ioutil.TempFile("", "srcdb") if err != nil { die("Failed to create source index database", err) } srcDbF.Close() defer os.RemoveAll(srcDbF.Name()) srcRepo, err := sqlite3.NewDbRepo(srcDbF.Name()) if err != nil { die("Failed to create source index database", err) } srcStore, err := fs.NewLocalStore(srcpath, srcRepo) if err != nil { die(fmt.Sprintf("Failed to read source %s", srcpath), err) } dstDbF, err := ioutil.TempFile("", "dstdb") if err != nil { die("Failed to create destination index database", err) } defer os.RemoveAll(dstDbF.Name()) dstRepo, err := sqlite3.NewDbRepo(dstDbF.Name()) if err != nil { die("Failed to create source index database", err) } dstStore, err := fs.NewLocalStore(dstpath, dstRepo) if err != nil { die(fmt.Sprintf("Failed to read destination %s", srcpath), err) } patchPlan := sync.NewPatchPlan(srcStore, dstStore) if verboseOpt.Value { fmt.Printf("%v\n", patchPlan) } failedCmd, err := patchPlan.Exec() if err != nil { die(failedCmd.String(), err) } os.Exit(0) }