// TreeLookup gets the contents of a certain file path in the given tree func TreeLookup(objects *bolt.Bucket, tree *types.TreeObject, filepath string) []byte { // Split the path into sperate components components := strings.Split(filepath, string(os.PathSeparator)) if !tree.HasFile(components[0]) { log.Fatalln("tree object does not have file " + components[0]) } hash := tree.GetFile(components[0]) if len(components) > 1 { // If there is more than one component left, expect the object to be another directory. nextTree := types.DeserializeTreeObject(objects.Get(hash)) return TreeLookup(objects, nextTree, strings.Join(components[1:], string(os.PathSeparator))) } // Return the file data stored by that hash. return objects.Get(hash) }
// 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 }