mirror of
https://github.com/cupcakearmy/autorestic.git
synced 2024-11-05 05:04:13 +01:00
1.7.0 (#188)
* stream the output (#186) * dont duplicate global flags (#187) * docs for tagging * fix self update path (#190) * version bump & changelog
This commit is contained in:
parent
ff2e3714d1
commit
5bcf5c9217
14
CHANGELOG.md
14
CHANGELOG.md
@ -5,11 +5,23 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [1.7.0] - 2022-04-27
|
||||
|
||||
### Changed
|
||||
|
||||
- #147 Stream output instead of buffering.
|
||||
|
||||
### Fixed
|
||||
|
||||
- #184 duplicate global options.
|
||||
- #154 add docs for migration.
|
||||
- #182 fix bug with upgrading custom restic with custom path.
|
||||
|
||||
## [1.6.2] - 2022-04-14
|
||||
|
||||
### Fixed
|
||||
|
||||
- Version bump in code
|
||||
- Version bump in code.
|
||||
|
||||
## [1.6.1] - 2022-04-14
|
||||
|
||||
|
@ -40,7 +40,7 @@ func init() {
|
||||
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file (default is $HOME/.autorestic.yml or ./.autorestic.yml)")
|
||||
rootCmd.PersistentFlags().BoolVar(&flags.CI, "ci", false, "CI mode disabled interactive mode and colors and enables verbosity")
|
||||
rootCmd.PersistentFlags().BoolVarP(&flags.VERBOSE, "verbose", "v", false, "verbose mode")
|
||||
rootCmd.PersistentFlags().StringVar(&internal.RESTIC_BIN, "restic-bin", "restic", "specify custom restic binary")
|
||||
rootCmd.PersistentFlags().StringVar(&flags.RESTIC_BIN, "restic-bin", "restic", "specify custom restic binary")
|
||||
cobra.OnInitialize(initConfig)
|
||||
}
|
||||
|
||||
|
@ -57,4 +57,12 @@ locations:
|
||||
type: volume
|
||||
```
|
||||
|
||||
## Tagging
|
||||
|
||||
Autorestic changed the way backups are referenced. Before we took the paths as the identifying information. Now autorestic uses native restic tags to reference them. This means that old backups are not referenced. You can the old snapshots manually. An example can be shown below.
|
||||
|
||||
```bash
|
||||
autorestic exec -va -- tag --add ar:location:LOCATION_NAME # Only if you have only one location
|
||||
```
|
||||
|
||||
> :ToCPrevNext
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/cupcakearmy/autorestic/internal/colors"
|
||||
"github.com/cupcakearmy/autorestic/internal/flags"
|
||||
)
|
||||
|
||||
type BackendRest struct {
|
||||
@ -120,18 +119,15 @@ func (b Backend) validate() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
options := ExecuteOptions{Envs: env}
|
||||
options := ExecuteOptions{Envs: env, Silent: true}
|
||||
// Check if already initialized
|
||||
_, _, err = ExecuteResticCommand(options, "snapshots")
|
||||
_, _, err = ExecuteResticCommand(options, "check")
|
||||
if err == nil {
|
||||
return nil
|
||||
} else {
|
||||
// If not initialize
|
||||
colors.Body.Printf("Initializing backend \"%s\"...\n", b.name)
|
||||
_, out, err := ExecuteResticCommand(options, "init")
|
||||
if flags.VERBOSE {
|
||||
colors.Faint.Println(out)
|
||||
}
|
||||
_, _, err := ExecuteResticCommand(options, "init")
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -147,9 +143,6 @@ func (b Backend) Exec(args []string) error {
|
||||
colors.Error.Println(out)
|
||||
return err
|
||||
}
|
||||
if flags.VERBOSE {
|
||||
colors.Faint.Println(out)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/cupcakearmy/autorestic/internal"
|
||||
"github.com/cupcakearmy/autorestic/internal/colors"
|
||||
"github.com/cupcakearmy/autorestic/internal/flags"
|
||||
)
|
||||
|
||||
const INSTALL_PATH = "/usr/local/bin"
|
||||
@ -128,10 +129,9 @@ func InstallRestic() error {
|
||||
}
|
||||
|
||||
func upgradeRestic() error {
|
||||
_, out, err := internal.ExecuteCommand(internal.ExecuteOptions{
|
||||
Command: "restic",
|
||||
_, _, err := internal.ExecuteCommand(internal.ExecuteOptions{
|
||||
Command: flags.RESTIC_BIN,
|
||||
}, "self-update")
|
||||
colors.Faint.Println(out)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
const VERSION = "1.6.2"
|
||||
const VERSION = "1.7.0"
|
||||
|
||||
type OptionMap map[string][]interface{}
|
||||
type Options map[string]OptionMap
|
||||
@ -185,7 +185,7 @@ func CheckConfig() error {
|
||||
return fmt.Errorf("config could not be loaded/found")
|
||||
}
|
||||
if !CheckIfResticIsCallable() {
|
||||
return fmt.Errorf(`%s was not found. Install either with "autorestic install" or manually`, RESTIC_BIN)
|
||||
return fmt.Errorf(`%s was not found. Install either with "autorestic install" or manually`, flags.RESTIC_BIN)
|
||||
}
|
||||
for name, backend := range c.Backends {
|
||||
backend.name = name
|
||||
@ -295,12 +295,8 @@ func appendOptionsToSlice(str *[]string, options OptionMap) {
|
||||
}
|
||||
}
|
||||
|
||||
func getOptions(options Options, key string) []string {
|
||||
func getOptions(options Options, keys []string) []string {
|
||||
var selected []string
|
||||
var keys = []string{"all"}
|
||||
if key != "" {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
for _, key := range keys {
|
||||
appendOptionsToSlice(&selected, options[key])
|
||||
}
|
||||
@ -310,9 +306,9 @@ func getOptions(options Options, key string) []string {
|
||||
func combineOptions(key string, l Location, b Backend) []string {
|
||||
// Priority: location > backend > global
|
||||
var options []string
|
||||
gFlags := getOptions(GetConfig().Global, key)
|
||||
bFlags := getOptions(b.Options, key)
|
||||
lFlags := getOptions(l.Options, key)
|
||||
gFlags := getOptions(GetConfig().Global, []string{key})
|
||||
bFlags := getOptions(b.Options, []string{"all", key})
|
||||
lFlags := getOptions(l.Options, []string{"all", key})
|
||||
options = append(options, gFlags...)
|
||||
options = append(options, bFlags...)
|
||||
options = append(options, lFlags...)
|
||||
|
@ -1,5 +1,8 @@
|
||||
package flags
|
||||
|
||||
var CI bool = false
|
||||
var VERBOSE bool = false
|
||||
var CRON_LEAN bool = false
|
||||
var (
|
||||
CI bool = false
|
||||
VERBOSE bool = false
|
||||
CRON_LEAN bool = false
|
||||
RESTIC_BIN string
|
||||
)
|
||||
|
@ -146,9 +146,6 @@ func (l Location) ExecuteHooks(commands []string, options ExecuteOptions) error
|
||||
colors.Error.Println(out)
|
||||
return err
|
||||
}
|
||||
if flags.VERBOSE {
|
||||
colors.Faint.Println(out)
|
||||
}
|
||||
}
|
||||
colors.Body.Println("")
|
||||
return nil
|
||||
@ -284,24 +281,16 @@ func (l Location) Backup(cron bool, specificBackend string) []error {
|
||||
for k, v := range env2 {
|
||||
env[k+"2"] = v
|
||||
}
|
||||
_, out, err := ExecuteResticCommand(ExecuteOptions{
|
||||
_, _, err := ExecuteResticCommand(ExecuteOptions{
|
||||
Envs: env,
|
||||
}, "copy", md.SnapshotID)
|
||||
|
||||
if flags.VERBOSE {
|
||||
colors.Faint.Println(out)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if flags.VERBOSE {
|
||||
colors.Faint.Println(out)
|
||||
}
|
||||
}
|
||||
|
||||
// After hooks
|
||||
@ -353,10 +342,7 @@ func (l Location) Forget(prune bool, dry bool) error {
|
||||
cmd = append(cmd, "--dry-run")
|
||||
}
|
||||
cmd = append(cmd, combineOptions("forget", l, backend)...)
|
||||
_, out, err := ExecuteResticCommand(options, cmd...)
|
||||
if flags.VERBOSE {
|
||||
colors.Faint.Println(out)
|
||||
}
|
||||
_, _, err = ExecuteResticCommand(options, cmd...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -9,23 +9,34 @@ import (
|
||||
|
||||
"github.com/cupcakearmy/autorestic/internal/colors"
|
||||
"github.com/cupcakearmy/autorestic/internal/flags"
|
||||
"github.com/fatih/color"
|
||||
)
|
||||
|
||||
var RESTIC_BIN string
|
||||
|
||||
func CheckIfCommandIsCallable(cmd string) bool {
|
||||
_, err := exec.LookPath(cmd)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func CheckIfResticIsCallable() bool {
|
||||
return CheckIfCommandIsCallable(RESTIC_BIN)
|
||||
return CheckIfCommandIsCallable(flags.RESTIC_BIN)
|
||||
}
|
||||
|
||||
type ExecuteOptions struct {
|
||||
Command string
|
||||
Envs map[string]string
|
||||
Dir string
|
||||
Silent bool
|
||||
}
|
||||
|
||||
type ColoredWriter struct {
|
||||
target io.Writer
|
||||
color *color.Color
|
||||
}
|
||||
|
||||
func (w ColoredWriter) Write(p []byte) (n int, err error) {
|
||||
colored := []byte(w.color.Sprint(string(p)))
|
||||
w.target.Write(colored)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func ExecuteCommand(options ExecuteOptions, args ...string) (int, string, error) {
|
||||
@ -43,23 +54,32 @@ func ExecuteCommand(options ExecuteOptions, args ...string) (int, string, error)
|
||||
|
||||
var out bytes.Buffer
|
||||
var error bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
if flags.VERBOSE && !options.Silent {
|
||||
var colored ColoredWriter = ColoredWriter{
|
||||
target: os.Stdout,
|
||||
color: colors.Faint,
|
||||
}
|
||||
mw := io.MultiWriter(colored, &out)
|
||||
cmd.Stdout = mw
|
||||
} else {
|
||||
cmd.Stdout = &out
|
||||
}
|
||||
cmd.Stderr = &error
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
code := -1
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
return exitError.ExitCode(), error.String(), err
|
||||
} else {
|
||||
return -1, error.String(), err
|
||||
code = exitError.ExitCode()
|
||||
}
|
||||
return code, error.String(), err
|
||||
}
|
||||
return 0, out.String(), nil
|
||||
}
|
||||
|
||||
func ExecuteResticCommand(options ExecuteOptions, args ...string) (int, string, error) {
|
||||
options.Command = RESTIC_BIN
|
||||
options.Command = flags.RESTIC_BIN
|
||||
var c = GetConfig()
|
||||
var optionsAsString = getOptions(c.Global, "")
|
||||
var optionsAsString = getOptions(c.Global, []string{"all"})
|
||||
args = append(optionsAsString, args...)
|
||||
return ExecuteCommand(options, args...)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user