2
2
mirror of https://github.com/octoleo/restic.git synced 2024-11-04 12:34:13 +00:00

Merge pull request #817 from restic/add-forget-prune

Add `--prune` switch to `forget`
This commit is contained in:
Alexander Neumann 2017-02-21 11:40:30 +01:00
commit 3d1dc636d0
3 changed files with 55 additions and 3 deletions

View File

@ -545,7 +545,8 @@ be done either manually (by specifying a snapshot ID to remove) or by using a
policy that describes which snapshots to forget. For all remove operations, two policy that describes which snapshots to forget. For all remove operations, two
commands need to be called in sequence: `forget` to remove a snapshot and commands need to be called in sequence: `forget` to remove a snapshot and
`prune` to actually remove the data that was referenced by the snapshot from `prune` to actually remove the data that was referenced by the snapshot from
the repository. the repository. This can be automated with the `--prune` option of the `forget`
command, which runs `prune` automatically if snapshots have been removed.
## Remove a single snapshot ## Remove a single snapshot
@ -610,6 +611,41 @@ done
Afterwards the repository is smaller. Afterwards the repository is smaller.
You can automate this two-step process by using the `--prune` switch to
`forget`:
```console
$ restic forget --keep-last 1 --prune
snapshots for host mopped, directories /home/user/work:
keep 1 snapshots:
ID Date Host Tags Directory
----------------------------------------------------------------------
4bba301e 2017-02-21 10:49:18 mopped /home/user/work
remove 1 snapshots:
ID Date Host Tags Directory
----------------------------------------------------------------------
8c02b94b 2017-02-21 10:48:33 mopped /home/user/work
1 snapshots have been removed, running prune
counting files in repo
building new index for repo
[0:00] 100.00% 37 / 37 packs
repository contains 37 packs (5521 blobs) with 151.012 MiB bytes
processed 5521 blobs: 0 duplicate blobs, 0B duplicate
load all snapshots
find data that is still in use for 1 snapshots
[0:00] 100.00% 1 / 1 snapshots
found 5323 of 5521 data blobs still in use, removing 198 blobs
will delete 0 packs and rewrite 27 packs, this frees 22.106 MiB
creating new index
[0:00] 100.00% 30 / 30 packs
saved new index as b49f3e68
done
```
## Removing snapshots according to a policy ## Removing snapshots according to a policy
Removing snapshots manually is tedious and error-prone, therefore restic allows Removing snapshots manually is tedious and error-prone, therefore restic allows
@ -747,4 +783,4 @@ enter password for repository:
Restic supports the output of some commands in JSON format. The JSON flag ```--json``` is currently supported only by ```restic snapshots```. Restic supports the output of some commands in JSON format. The JSON flag ```--json``` is currently supported only by ```restic snapshots```.
```console ```console
$ restic -r /tmp/backup snapshots --json``` $ restic -r /tmp/backup snapshots --json```

View File

@ -38,6 +38,7 @@ type ForgetOptions struct {
Tags []string Tags []string
DryRun bool DryRun bool
Prune bool
} }
var forgetOptions ForgetOptions var forgetOptions ForgetOptions
@ -58,6 +59,7 @@ func init() {
f.StringSliceVar(&forgetOptions.Tags, "tag", []string{}, "only forget snapshots with the `tag` (can be specified multiple times)") f.StringSliceVar(&forgetOptions.Tags, "tag", []string{}, "only forget snapshots with the `tag` (can be specified multiple times)")
f.BoolVarP(&forgetOptions.DryRun, "dry-run", "n", false, "do not delete anything, just print what would be done") f.BoolVarP(&forgetOptions.DryRun, "dry-run", "n", false, "do not delete anything, just print what would be done")
f.BoolVar(&forgetOptions.Prune, "prune", false, "automatically run the 'prune' command if snapshots have been removed")
} }
func printSnapshots(w io.Writer, snapshots restic.Snapshots) { func printSnapshots(w io.Writer, snapshots restic.Snapshots) {
@ -188,6 +190,7 @@ func runForget(opts ForgetOptions, gopts GlobalOptions, args []string) error {
snapshotGroups[k] = list snapshotGroups[k] = list
} }
removeSnapshots := 0
for key, snapshotGroup := range snapshotGroups { for key, snapshotGroup := range snapshotGroups {
Printf("snapshots for host %v, directories %v:\n\n", key.Hostname, key.Dirs) Printf("snapshots for host %v, directories %v:\n\n", key.Hostname, key.Dirs)
keep, remove := restic.ApplyPolicy(snapshotGroup, policy) keep, remove := restic.ApplyPolicy(snapshotGroup, policy)
@ -200,6 +203,8 @@ func runForget(opts ForgetOptions, gopts GlobalOptions, args []string) error {
printSnapshots(globalOptions.stdout, remove) printSnapshots(globalOptions.stdout, remove)
Printf("\n") Printf("\n")
removeSnapshots += len(remove)
if !opts.DryRun { if !opts.DryRun {
for _, sn := range remove { for _, sn := range remove {
h := restic.Handle{Type: restic.SnapshotFile, Name: sn.ID().String()} h := restic.Handle{Type: restic.SnapshotFile, Name: sn.ID().String()}
@ -211,5 +216,12 @@ func runForget(opts ForgetOptions, gopts GlobalOptions, args []string) error {
} }
} }
if removeSnapshots > 0 && opts.Prune {
Printf("%d snapshots have been removed, running prune\n", removeSnapshots)
if !opts.DryRun {
return pruneRepository(gopts, repo)
}
}
return nil return nil
} }

View File

@ -75,7 +75,11 @@ func runPrune(gopts GlobalOptions) error {
return err return err
} }
err = repo.LoadIndex() return pruneRepository(gopts, repo)
}
func pruneRepository(gopts GlobalOptions, repo restic.Repository) error {
err := repo.LoadIndex()
if err != nil { if err != nil {
return err return err
} }