handler_file.go 2.07 KB
Newer Older
ale's avatar
ale committed
1 2 3 4
package tabacco

import (
	"context"
5 6
	"fmt"
	"io/ioutil"
ale's avatar
ale committed
7
	"path/filepath"
ale's avatar
ale committed
8

ale's avatar
ale committed
9
	"git.autistici.org/ai3/tools/tabacco/jobs"
ale's avatar
ale committed
10 11 12 13 14 15
)

type fileHandler struct {
	path string
}

ale's avatar
ale committed
16
func newFileHandler(name string, params Params) (Handler, error) {
17
	return &fileHandler{path: params.Get("path")}, nil
18 19
}

ale's avatar
ale committed
20 21 22 23 24 25 26
// Convert the atom to a path.
func atomPath(a Atom, root string) string {
	// If the atom has a path, use that.
	if a.Path != "" {
		// If it's an absolute path, just use it.
		if a.Path[0] == '/' {
			return a.Path
ale's avatar
ale committed
27
		}
ale's avatar
ale committed
28 29
		// Otherwise join it with the root path.
		return filepath.Join(root, a.Path)
ale's avatar
ale committed
30
	}
ale's avatar
ale committed
31 32
	// Join the name with the root path by default.
	return filepath.Join(root, a.Name)
ale's avatar
ale committed
33 34
}

35 36 37 38 39 40 41 42 43 44
func (h *fileHandler) saveAtomsToFile(ctx context.Context, atoms []Atom) (string, error) {
	tmpf, err := ioutil.TempFile(getWorkDir(ctx), "file-list-")
	if err != nil {
		return "", err
	}
	for _, a := range atoms {
		path := atomPath(a, h.path)
		if _, err := fmt.Fprintf(tmpf, "%s\n", path); err != nil {
			return "", err
		}
ale's avatar
ale committed
45
	}
46 47
	return tmpf.Name(), tmpf.Close()
}
ale's avatar
ale committed
48

49
func (h *fileHandler) BackupJob(rctx RuntimeContext, backup *Backup, ds *Dataset) jobs.Job {
ale's avatar
ale committed
50
	return jobs.JobFunc(func(ctx context.Context) error {
51 52 53 54 55 56 57 58 59 60 61
		// Build the list of filesystem paths to pass to the
		// Repository.Backup method. Use a temporary file, in case
		// the path list is too long for the command line.
		tmpf, err := h.saveAtomsToFile(ctx, ds.Atoms)
		if err != nil {
			return err
		}

		cmd := rctx.Repo().BackupCmd(backup, ds, tmpf)

		// Now pass those paths to the Backup method.
ale's avatar
ale committed
62
		return rctx.Shell().Run(ctx, cmd)
ale's avatar
ale committed
63 64 65
	})
}

ale's avatar
ale committed
66
func (h *fileHandler) RestoreJob(rctx RuntimeContext, backup *Backup, ds *Dataset, target string) jobs.Job {
ale's avatar
ale committed
67 68 69 70 71 72
	// Build the list of filesystem paths to pass to the
	// Repository.Backup method.
	var paths []string
	for _, a := range ds.Atoms {
		paths = append(paths, atomPath(a, h.path))
	}
ale's avatar
ale committed
73

ale's avatar
ale committed
74
	// Call the repo Restore method.
ale's avatar
ale committed
75
	return jobs.JobFunc(func(ctx context.Context) error {
ale's avatar
ale committed
76
		cmd, err := rctx.Repo().RestoreCmd(ctx, rctx, backup, ds, paths, target)
ale's avatar
ale committed
77 78 79 80
		if err != nil {
			return err
		}
		return rctx.Shell().Run(ctx, cmd)
ale's avatar
ale committed
81
	})
ale's avatar
ale committed
82
}