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 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 }
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 Match(src string, dst string) (match *FileMatch, err os.Error) { srcFileInfo, srcBlocksInfo, err := fs.IndexFile(src) if err != nil { return nil, err } repo := fs.NewMemRepo() srcFile := repo.AddFile(nil, srcFileInfo, srcBlocksInfo) match, err = MatchFile(srcFile, dst) return match, err }
// Test the matcher on a case where the source file has the same // prefix as destination, but has been appended to. func TestMatchAppend(t *testing.T) { tg := treegen.New() treeSpec := tg.F("bar", tg.B(42, 65537), tg.B(43, 65537)) srcpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(srcpath) // Try indexing root dir as a file srcFileInfo, srcBlocksInfo, err := fs.IndexFile(srcpath) assert.Tf(t, err != nil, "%v", err) // Ok, for real this time srcFileInfo, srcBlocksInfo, err = fs.IndexFile(filepath.Join(srcpath, "bar")) assert.Tf(t, err == nil, "%v", err) assert.Equal(t, 17, len(srcBlocksInfo)) tg = treegen.New() treeSpec = tg.F("bar", tg.B(42, 65537)) dstpath := treegen.TestTree(t, treeSpec) defer os.RemoveAll(dstpath) _, dstBlocksInfo, err := fs.IndexFile(filepath.Join(dstpath, "bar")) assert.Equal(t, 9, len(dstBlocksInfo)) srcRepo := fs.NewMemRepo() srcFile := srcRepo.AddFile(nil, srcFileInfo, srcBlocksInfo) match, err := MatchFile(srcFile, filepath.Join(dstpath, "bar")) assert.T(t, err == nil, "%v", err) assert.Equal(t, 8, len(match.BlockMatches)) notMatched := match.NotMatched() assert.Equal(t, 1, len(notMatched)) assert.Equal(t, int64(65536), notMatched[0].From) assert.Equal(t, int64(65537+65537), notMatched[0].To) }
func TestFsParentRefs(t *testing.T) { DoTestParentRefs(t, fs.NewMemRepo()) }
func TestFsDirDescent(t *testing.T) { DoTestDirDescent(t, fs.NewMemRepo()) }
func TestFsDirResolve(t *testing.T) { DoTestDirResolve(t, fs.NewMemRepo()) }
func TestFsStoreRelPath(t *testing.T) { DoTestStoreRelPath(t, fs.NewMemRepo()) }
func TestFsNodeRelPath(t *testing.T) { DoTestNodeRelPath(t, fs.NewMemRepo()) }
func TestFsVisitBlocks(t *testing.T) { DoTestVisitBlocks(t, fs.NewMemRepo()) }
func TestFsVisitDirsOnly(t *testing.T) { DoTestVisitDirsOnly(t, fs.NewMemRepo()) }
func TestFsDirIndex(t *testing.T) { DoTestDirIndex(t, fs.NewMemRepo()) }
func mkMemRepo(_ *testing.T) fs.NodeRepo { return fs.NewMemRepo() }