예제 #1
0
파일: srv.go 프로젝트: cmars/replican-web
func TreeHandler(store fs.LocalStore) http.HandlerFunc {
	return func(resp http.ResponseWriter, req *http.Request) {
		setBinaryResp(resp)

		// gob the root
		buffer := bytes.NewBuffer([]byte{})
		encoder := gob.NewEncoder(buffer)
		err := encoder.Encode(store.Root())
		if err != nil {
			writeResponseError(resp, http.StatusInternalServerError, err.String())
			return
		}

		rootGob := buffer.Bytes()

		resp.Write(rootGob)
	}
}
예제 #2
0
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.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.Root(), func(srcNode fs.Node) bool {

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

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

		// Remove this srcPath from dst unmatched, if it was present
		delete(plan.dstFileUnmatch, srcPath)

		dstNode, hasDstNode := dstStore.Index().StrongFsNode(srcNode.Strong())

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

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

		//		fmt.Printf("srcPath=%s hasDstNode=%v isDstFsNode=%v isSrcFile=%v, isDstFile=%v\n%v\n\n",
		//			srcPath, hasDstNode, isDstFsNode, isSrcFile, isDstFile, dstNode)

		// 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

			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
}