Exemplo n.º 1
0
// TakeSnapshot recursivelly snapshots the current directory.
func TakeSnapshot(b *bolt.Bucket, filePath string) types.Hash {
	// Determine if path is a directory or a file
	info, err := os.Stat(filePath)
	if err != nil {
		log.Fatalln("Could not call os.Stat on " + filePath)
	}

	if info.IsDir() {
		// If the path is a directory, we need to create a tree object
		treeObject := types.NewTreeObject()

		// Enumerate all of the files in this directory
		files, err := ioutil.ReadDir(filePath)
		if err != nil {
			log.Fatalf("Could not list files in dir %s: %v", filePath, err)
		}
		for _, file := range files {
			if util.IgnorePath(file.Name()) {
				continue
			}

			// Snapshot the file, and add it to the current tree object
			hash := TakeSnapshot(b, path.Join(filePath, file.Name()))
			treeObject.AddFile(file.Name(), hash, file.IsDir())
		}

		// Calculate hash of the directory
		serialized := treeObject.Serialize()
		hash := types.CalculateHash(serialized)

		// Put directory into database, addressed by it's hash
		b.Put(hash, serialized)
		util.DebugLog("Put directory \"" + filePath + "\" into database with hash " + hash.String())
		return hash
	}

	// Calculate hash of file contents
	file, err := ioutil.ReadFile(filePath)
	if err != nil {
		panic(err.Error())
	}
	hash := types.CalculateHash(file)

	// Put file into database, addressed by it's hash
	b.Put(hash, file)
	util.DebugLog("Put file \"" + filePath + "\" into database with hash " + hash.String())
	return hash
}
Exemplo n.º 2
0
// TreeDiff lists the differences between a Tree object in a snapshot
// and a filesystem path.
func TreeDiff(objects *bolt.Bucket, treeHash types.Hash, dir string) []Difference {
	differences := []Difference{}

	// Try to list all of the files in this directory.
	files, listErr := ioutil.ReadDir(dir)
	// Try to load in the tree object.
	var treeObject *types.TreeObject = nil
	if !treeHash.Equal(types.EMPTY) {
		treeObject = types.DeserializeTreeObject(objects.Get(treeHash))
	}

	// For each file in the current directory, determine if the file was either added or modified.
	if listErr == nil {
		for _, file := range files {
			if util.IgnorePath(file.Name()) {
				continue
			}

			if file.IsDir() {
				if treeObject == nil {
					differences = append(differences, TreeDiff(objects, types.EMPTY, path.Join(dir, file.Name()))...)
				} else {
					if treeObject.HasFile(file.Name()) {
						differences = append(differences, TreeDiff(objects, treeObject.GetFile(file.Name()), path.Join(dir, file.Name()))...)
					} else {
						differences = append(differences, TreeDiff(objects, types.EMPTY, path.Join(dir, file.Name()))...)
					}
				}
			} else {
				if treeObject == nil {
					differences = append(differences, Difference{
						Type:     "A",
						FilePath: path.Join(dir, file.Name()),
					})
				} else {
					if treeObject.HasFile(file.Name()) {
						fileBytes, err := ioutil.ReadFile(path.Join(dir, file.Name()))
						if err != nil {
							panic(err)
						}
						if !types.CalculateHash(fileBytes).Equal(treeObject.GetFile(file.Name())) {
							differences = append(differences, Difference{
								Type:     "M",
								FilePath: path.Join(dir, file.Name()),
							})
						}
					} else {
						differences = append(differences, Difference{
							Type:     "A",
							FilePath: path.Join(dir, file.Name()),
						})
					}
				}
			}
		}
	}

	// For each file in the the tree object, see if that file was removed in the working directory
	if treeObject != nil {
		for _, entry := range treeObject.Files {
			if !listHasFile(files, entry.Name) {
				if entry.IsDir {
					differences = append(differences, TreeDiff(objects, entry.Hash, path.Join(dir, entry.Name))...)

				} else {
					differences = append(differences, Difference{
						Type:     "R",
						FilePath: path.Join(dir, entry.Name),
					})

				}
			}
		}
	}

	return differences
}