Ejemplo n.º 1
0
// Revert implements got revert
func Revert(c *cli.Context) {
	// Open the database
	db := util.OpenDB()
	defer db.Close()

	// Perform operations in a read-only lock
	err := db.View(func(tx *bolt.Tx) error {
		// Get the current commit sha
		info := tx.Bucket(util.INFO)
		objects := tx.Bucket(util.OBJECTS)
		current := info.Get(util.CURRENT)

		// Get the commit object and associated tree
		commit := types.DeserializeCommitObject(objects.Get(current))
		tree := types.DeserializeTreeObject(objects.Get(commit.Tree))

		for _, file := range c.Args() {
			fmt.Println("Reverting " + file + "...")
			fileData := TreeLookup(objects, tree, path.Clean(file))
			ioutil.WriteFile(file, fileData, 0644)
		}

		return nil
	})

	if err != nil {
		log.Fatal("Error reading from the database.")
	}
}
Ejemplo n.º 2
0
// 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)
}
Ejemplo n.º 3
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
}