Ejemplo n.º 1
0
// send produces a binary diff stream and passes it to cont
func send(repo, commit string, cont func(io.Reader) error) error {
	parent := GetMeta(path.Join(repo, commit), "parent")
	if parent == "" {
		return util.CallCont(exec.Command("btrfs", "send", FilePath(path.Join(repo, commit))), cont)
	} else {
		return util.CallCont(exec.Command("btrfs", "send", "-p",
			FilePath(path.Join(repo, parent)), FilePath(path.Join(repo, commit))), cont)
	}
}
Ejemplo n.º 2
0
// transid returns transid of a path in a repo. This function is used in
// several other internal functions.
func transid(repo, commit string) (string, error) {
	//  "9223372036854775810" == 2 ** 63 we use a very big number there so that
	//  we get the transid of the from path. According to the internet this is
	//  the nicest way to get it from btrfs.
	var transid string
	c := exec.Command("btrfs", "subvolume", "find-new", FilePath(path.Join(repo, commit)), "9223372036854775808")
	err := util.CallCont(c, func(r io.Reader) error {
		scanner := bufio.NewScanner(r)
		for scanner.Scan() {
			// scanner.Text() looks like this:
			// transid marker was 907
			// 0       1      2   3
			tokens := strings.Split(scanner.Text(), " ")
			if len(tokens) != 4 {
				return fmt.Errorf("Failed to parse find-new output.")
			}
			// We want to increment the transid because it's inclusive, if we
			// don't increment we'll get things from the previous commit as
			// well.
			transid = tokens[3]
		}
		return scanner.Err()
	})
	if err != nil {
		return "", err
	}
	return transid, err
}
Ejemplo n.º 3
0
// FindNew returns an array of filenames that were created or modified between `from` and `to`
func FindNew(repo, from, to string) ([]string, error) {
	var files []string
	t, err := transid(repo, from)
	if err != nil {
		return files, err
	}
	c := exec.Command("btrfs", "subvolume", "find-new", FilePath(path.Join(repo, to)), t)
	err = util.CallCont(c, func(r io.Reader) error {
		scanner := bufio.NewScanner(r)
		for scanner.Scan() {
			log.Print(scanner.Text())
			// scanner.Text() looks like this:
			// inode 6683 file offset 0 len 107 disk start 0 offset 0 gen 909 flags INLINE jobs/rPqZxsaspy
			// 0     1    2    3      4 5   6   7    8     9 10     11 12 13 14     15     16
			tokens := strings.Split(scanner.Text(), " ")
			// Make sure the line is parseable as a file and the path isn't hidden.
			if len(tokens) == 17 {
				if !strings.HasPrefix(tokens[16], ".") { // check if it's a hidden file
					files = append(files, tokens[16])
				}
			} else if len(tokens) == 4 {
				continue //skip transid messages
			} else {
				return fmt.Errorf("Failed to parse find-new output.")
			}
		}
		return scanner.Err()
	})
	return files, err
}
Ejemplo n.º 4
0
//_log returns all of the commits the repo which have generation >= from.
func _log(repo, from string, order int, cont func(io.Reader) error) error {
	var sort string
	if order == Desc {
		sort = "-ogen"
	} else {
		sort = "+ogen"
	}

	if from == "" {
		c := exec.Command("btrfs", "subvolume", "list", "-o", "-c", "-u", "-q", "--sort", sort, FilePath(path.Join(repo)))
		return util.CallCont(c, cont)
	} else {
		t, err := transid(repo, from)
		if err != nil {
			return err
		}
		c := exec.Command("btrfs", "subvolume", "list", "-o", "-c", "-u", "-q", "-C", "+"+t, "--sort", sort, FilePath(path.Join(repo)))
		return util.CallCont(c, cont)
	}
}
Ejemplo n.º 5
0
// IsCommit returns true if the volume is a commit and false if it's a branch.
func IsCommit(name string) (bool, error) {
	var res bool
	// "-t s" indicates to btrfs that this is a subvolume without the "-t s"
	// btrfs will still output what we want, but it will have a nonzero return
	// code
	err := util.CallCont(exec.Command("btrfs", "property", "get", "-t", "s", FilePath(name)),
		func(r io.Reader) error {
			scanner := bufio.NewScanner(r)
			for scanner.Scan() {
				if strings.Contains(scanner.Text(), "ro=true") {
					res = true
					return nil
				}
			}
			return scanner.Err()
		})
	return res, err
}