Skip to content

Commit

Permalink
Add --prefix and --strip-components options on backup.
Browse files Browse the repository at this point in the history
  • Loading branch information
giacomocariello committed Sep 25, 2018
1 parent 6bc99ce commit 7ffbae2
Show file tree
Hide file tree
Showing 11 changed files with 54 additions and 24 deletions.
8 changes: 7 additions & 1 deletion cmd/restic/cmd_backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ type BackupOptions struct {
FilesFrom string
TimeStamp string
WithAtime bool
RootPrefix string
RootStrip int
}

var backupOptions BackupOptions
Expand All @@ -98,6 +100,8 @@ func init() {
f.StringVar(&backupOptions.FilesFrom, "files-from", "", "read the files to backup from file (can be combined with file args)")
f.StringVar(&backupOptions.TimeStamp, "time", "", "time of the backup (ex. '2012-11-01 22:08:41') (default: now)")
f.BoolVar(&backupOptions.WithAtime, "with-atime", false, "store the atime for all files and directories")
f.StringVar(&backupOptions.RootPrefix, "prefix", "", "apply a prefix to target paths")
f.IntVar(&backupOptions.RootStrip, "strip-components", 0, "strip NUMBER leading components from target paths")
}

// filterExisting returns a slice of all existing items, or an error if no
Expand Down Expand Up @@ -333,7 +337,7 @@ func findParentSnapshot(ctx context.Context, repo restic.Repository, opts Backup

// Find last snapshot to set it as parent, if not already set
if !opts.Force && parentID == nil {
id, err := restic.FindLatestSnapshot(ctx, repo, targets, []restic.TagList{}, opts.Hostname)
id, err := restic.FindLatestSnapshot(ctx, repo, targets, []restic.TagList{}, opts.Hostname, opts.RootPrefix, opts.RootStrip)
if err == nil {
parentID = &id
} else if err != restic.ErrNoSnapshotFound {
Expand Down Expand Up @@ -484,6 +488,8 @@ func runBackup(opts BackupOptions, gopts GlobalOptions, term *termstatus.Termina
Time: timeStamp,
Hostname: opts.Hostname,
ParentSnapshot: *parentSnapshotID,
RootPrefix: opts.RootPrefix,
RootStrip: opts.RootStrip,
}

uploader := archiver.IndexUploader{
Expand Down
2 changes: 1 addition & 1 deletion cmd/restic/cmd_dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func runDump(opts DumpOptions, gopts GlobalOptions, args []string) error {
var id restic.ID

if snapshotIDString == "latest" {
id, err = restic.FindLatestSnapshot(ctx, repo, opts.Paths, opts.Tags, opts.Host)
id, err = restic.FindLatestSnapshot(ctx, repo, opts.Paths, opts.Tags, opts.Host, "", 0)
if err != nil {
Exitf(1, "latest snapshot for criteria not found: %v Paths:%v Host:%v", err, opts.Paths, opts.Host)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/restic/cmd_restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func runRestore(opts RestoreOptions, gopts GlobalOptions, args []string) error {
var id restic.ID

if snapshotIDString == "latest" {
id, err = restic.FindLatestSnapshot(ctx, repo, opts.Paths, opts.Tags, opts.Host)
id, err = restic.FindLatestSnapshot(ctx, repo, opts.Paths, opts.Tags, opts.Host, "", 0)
if err != nil {
Exitf(1, "latest snapshot for criteria not found: %v Paths:%v Host:%v", err, opts.Paths, opts.Host)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/restic/cmd_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func runStats(gopts GlobalOptions, args []string) error {

var sID restic.ID
if snapshotIDString == "latest" {
sID, err = restic.FindLatestSnapshot(ctx, repo, []string{}, []restic.TagList{}, snapshotByHost)
sID, err = restic.FindLatestSnapshot(ctx, repo, []string{}, []restic.TagList{}, snapshotByHost, "", 0)
if err != nil {
return errors.Fatalf("latest snapshot for criteria not found: %v", err)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/restic/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func FindFilteredSnapshots(ctx context.Context, repo *repository.Repository, hos
// Process all snapshot IDs given as arguments.
for _, s := range snapshotIDs {
if s == "latest" {
id, err = restic.FindLatestSnapshot(ctx, repo, paths, tags, host)
id, err = restic.FindLatestSnapshot(ctx, repo, paths, tags, host, "", 0)
if err != nil {
Warnf("Ignoring %q, no snapshot matched given filter (Paths:%v Tags:%v Host:%v)\n", s, paths, tags, host)
usedFilter = true
Expand Down
4 changes: 3 additions & 1 deletion internal/archiver/archiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,8 @@ type SnapshotOptions struct {
Excludes []string
Time time.Time
ParentSnapshot restic.ID
RootPrefix string
RootStrip int
}

// loadParentTree loads a tree referenced by snapshot id. If id is null, nil is returned.
Expand Down Expand Up @@ -807,7 +809,7 @@ func (arch *Archiver) Snapshot(ctx context.Context, targets []string, opts Snaps
return nil, restic.ID{}, err
}

sn, err := restic.NewSnapshot(targets, opts.Tags, opts.Hostname, opts.Time)
sn, err := restic.NewSnapshot(targets, opts.Tags, opts.Hostname, opts.Time, opts.RootPrefix, opts.RootStrip)
sn.Excludes = opts.Excludes
if !opts.ParentSnapshot.IsNull() {
id := opts.ParentSnapshot
Expand Down
42 changes: 35 additions & 7 deletions internal/restic/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,45 @@ type Snapshot struct {
id *ID // plaintext ID, used during restore
}

func pathSplit(path string) (root string, lst []string) {
for root = filepath.Clean(path); ; {
var file string
root, file = filepath.Split(root)
if file == "" {
break
}
lst = append([]string{file}, lst...)
}
return
}

func pathMangle(path string, prefix string, strip int) string {
pathRoot, pathList := pathSplit(path)
if strip > 0 {
var stripRoot int
if pathRoot != "" {
stripRoot++
}
pathList = pathList[strip-stripRoot:]
pathRoot = ""
}
if prefix != "" {
pathRoot = prefix
} else {
absPath, err := filepath.Abs(pathRoot)
if err == nil {
pathRoot = absPath
}
}
return filepath.Join(append([]string{pathRoot}, pathList...)...)
}

// NewSnapshot returns an initialized snapshot struct for the current user and
// time.
func NewSnapshot(paths []string, tags []string, hostname string, time time.Time) (*Snapshot, error) {
func NewSnapshot(paths []string, tags []string, hostname string, time time.Time, prefix string, strip int) (*Snapshot, error) {
absPaths := make([]string, 0, len(paths))
for _, path := range paths {
p, err := filepath.Abs(path)
if err == nil {
absPaths = append(absPaths, p)
} else {
absPaths = append(absPaths, path)
}
absPaths = append(absPaths, pathMangle(path, prefix, strip))
}

sn := &Snapshot{
Expand Down
10 changes: 2 additions & 8 deletions internal/restic/snapshot_find.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,11 @@ import (
var ErrNoSnapshotFound = errors.New("no snapshot found")

// FindLatestSnapshot finds latest snapshot with optional target/directory, tags and hostname filters.
func FindLatestSnapshot(ctx context.Context, repo Repository, targets []string, tagLists []TagList, hostname string) (ID, error) {
func FindLatestSnapshot(ctx context.Context, repo Repository, targets []string, tagLists []TagList, hostname string, prefix string, strip int) (ID, error) {
var err error
absTargets := make([]string, 0, len(targets))
for _, target := range targets {
if !filepath.IsAbs(target) {
target, err = filepath.Abs(target)
if err != nil {
return ID{}, errors.Wrap(err, "Abs")
}
}
absTargets = append(absTargets, filepath.Clean(target))
absTargets = append(absTargets, pathMangle(target, prefix, strip))
}

var (
Expand Down
2 changes: 1 addition & 1 deletion internal/restic/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ import (
func TestNewSnapshot(t *testing.T) {
paths := []string{"/home/foobar"}

_, err := restic.NewSnapshot(paths, nil, "foo", time.Now())
_, err := restic.NewSnapshot(paths, nil, "foo", time.Now(), "", 0)
rtest.OK(t, err)
}
2 changes: 1 addition & 1 deletion internal/restic/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ func TestCreateSnapshot(t testing.TB, repo Repository, at time.Time, depth int,
t.Logf("create fake snapshot at %s with seed %d", at, seed)

fakedir := fmt.Sprintf("fakedir-at-%v", at.Format("2006-01-02 15:04:05"))
snapshot, err := NewSnapshot([]string{fakedir}, []string{"test"}, "foo", time.Now())
snapshot, err := NewSnapshot([]string{fakedir}, []string{"test"}, "foo", time.Now(), "", 0)
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/restorer/restorer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ func saveSnapshot(t testing.TB, repo restic.Repository, snapshot Snapshot) (*res
t.Fatal(err)
}

sn, err := restic.NewSnapshot([]string{"test"}, nil, "", time.Now())
sn, err := restic.NewSnapshot([]string{"test"}, nil, "", time.Now(), "", 0)
if err != nil {
t.Fatal(err)
}
Expand Down

0 comments on commit 7ffbae2

Please sign in to comment.