コード例 #1
0
ファイル: patch.go プロジェクト: cmars/replican-sync
func (sfd *SrcFileDownload) Exec(srcStore fs.BlockStore) os.Error {
	if err := mkParentDirs(sfd.Path); err != nil {
		return err
	}

	dstFh, err := os.Create(sfd.Path.Resolve())
	if dstFh == nil {
		return err
	}

	_, err = srcStore.ReadInto(sfd.SrcFile.Info().Strong, 0, sfd.SrcFile.Info().Size, dstFh)
	return err
}
コード例 #2
0
ファイル: patch.go プロジェクト: cmars/replican-sync
func NewPatchPlan(srcStore fs.BlockStore, dstStore fs.LocalStore) *PatchPlan {
	plan := &PatchPlan{srcStore: srcStore, dstStore: dstStore}

	plan.dstFileUnmatch = make(map[string]fs.File)

	fs.Walk(dstStore.Repo().Root(), func(dstNode fs.Node) bool {

		dstFile, isDstFile := dstNode.(fs.File)
		if isDstFile {
			plan.dstFileUnmatch[fs.RelPath(dstFile)] = dstFile
		}

		return !isDstFile
	})

	relocRefs := make(map[string]int)

	// Find all the FsNode matches
	fs.Walk(srcStore.Repo().Root(), func(srcNode fs.Node) bool {

		// Ignore non-FsNodes
		srcFsNode, isSrcFsNode := srcNode.(fs.FsNode)
		if !isSrcFsNode {
			return false
		}

		//		log.Printf("In src: %s", fs.RelPath(srcFsNode))

		srcFile, isSrcFile := srcNode.(fs.File)
		srcPath := fs.RelPath(srcFsNode)

		// Remove this srcPath from dst unmatched, if it was present
		plan.dstFileUnmatch[srcPath] = nil, false

		var srcStrong string
		if isSrcFile {
			srcStrong = srcFile.Info().Strong
		} else if srcDir, isSrcDir := srcNode.(fs.Dir); isSrcDir {
			srcStrong = srcDir.Info().Strong
		}

		var dstNode fs.FsNode
		var hasDstNode bool
		dstNode, hasDstNode = dstStore.Repo().File(srcStrong)
		if !hasDstNode {
			dstNode, hasDstNode = dstStore.Repo().Dir(srcStrong)
		}

		isDstFile := false
		if hasDstNode {
			_, isDstFile = dstNode.(fs.File)
		}

		dstFilePath := dstStore.Resolve(srcPath)
		dstFileInfo, _ := os.Stat(dstFilePath)

		// Resolve dst node that matches strong checksum with source
		if hasDstNode && isSrcFile == isDstFile {
			dstPath := fs.RelPath(dstNode)
			relocRefs[dstPath]++ // dstPath will be used in this cmd, inc ref count

			//			log.Printf("srcPath=%s dstPath=%s", srcPath, dstPath)

			if srcPath != dstPath {
				// Local dst file needs to be renamed or copied to src path
				from := &LocalPath{LocalStore: dstStore, RelPath: dstPath}
				to := &LocalPath{LocalStore: dstStore, RelPath: srcPath}
				plan.Cmds = append(plan.Cmds,
					&Transfer{From: from, To: to, relocRefs: relocRefs})
			} else {
				// Same path, keep it where it is
				plan.Cmds = append(plan.Cmds, &Keep{
					Path: &LocalPath{LocalStore: dstStore, RelPath: srcPath}})
			}

			// If its a file, figure out what to do with it
		} else if isSrcFile {

			switch {

			// Destination is not a file, so get rid of whatever is there first
			case dstFileInfo != nil && !dstFileInfo.IsRegular():
				plan.Cmds = append(plan.Cmds, &Conflict{
					Path:     &LocalPath{LocalStore: dstStore, RelPath: srcPath},
					FileInfo: dstFileInfo})
				fallthrough

			// Destination file does not exist, so full source copy needed
			case dstFileInfo == nil:
				plan.Cmds = append(plan.Cmds, &SrcFileDownload{
					SrcFile: srcFile,
					Path:    &LocalPath{LocalStore: dstStore, RelPath: srcPath}})
				break

			// Destination file exists, add block-level commands
			default:
				plan.appendFilePlan(srcFile, srcPath)
				break
			}

			// If its a directory, check for conflicting files of same name
		} else {

			if dstFileInfo != nil && !dstFileInfo.IsDirectory() {
				plan.Cmds = append(plan.Cmds, &Conflict{
					Path:     &LocalPath{LocalStore: dstStore, RelPath: dstFilePath},
					FileInfo: dstFileInfo})
			}
		}

		return !isSrcFile
	})

	return plan
}
コード例 #3
0
ファイル: patch.go プロジェクト: cmars/replican-sync
func (stc *SrcTempCopy) Exec(srcStore fs.BlockStore) os.Error {
	stc.Temp.tempFh.Seek(stc.TempOffset, 0)
	_, err := srcStore.ReadInto(stc.SrcStrong, stc.SrcOffset, stc.Length, stc.Temp.tempFh)
	return err
}