Linter updates

This commit is contained in:
IamTheFij 2022-02-22 16:55:41 -08:00
parent a1969b681a
commit 048e062102
8 changed files with 143 additions and 53 deletions

View File

@ -1,43 +1,105 @@
--- ---
linters: linters:
enable: enable:
- deadcode
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
- asciicheck - asciicheck
- bidichk
- bodyclose - bodyclose
- dogsled - containedctx
- contextcheck
- cyclop
- decorder
- depguard
- dupl - dupl
- durationcheck
- errchkjson
- errname
- errorlint
- exhaustive - exhaustive
- exhaustivestruct
- exportloopref
- forcetypeassert
- funlen
- gci
- gochecknoinits - gochecknoinits
- gocognit - gocognit
- goconst
- gocritic - gocritic
- gocyclo # - gocyclo # Using cyclop
- goerr113 - godot
- gofumpt # - goerr113 # Using errorlint
- gofmt
- goheader
- goimports - goimports
- gomnd - gomnd
- gomoddirectives
- gomodguard
- goprintffuncname - goprintffuncname
# - gosec - gosec
# - ifshort - grouper
- interfacer - ifshort
- maligned - importas
# - ireturn
- lll
- maintidx
- makezero
- misspell - misspell
- nakedret - nakedret
- nestif - nestif
- nilerr
- nilnil
- nlreturn - nlreturn
- noctx - noctx
- nolintlint
- paralleltest
- prealloc
- predeclared
# - promlinter # Not common enough
- revive
- rowserrcheck
- sqlclosecheck
# - stylecheck # Using revive
- tagliatelle
- tenv
- testpackage
- thelper
- tparallel
- unconvert
- unparam - unparam
- varnamelen
- wastedassign
- whitespace
- wrapcheck
- wsl - wsl
# - errorlint
disable: disable:
- gochecknoglobals - gochecknoglobals
- godox
- forbidigo
# Deprecated
- golint
- interfacer
- maligned
- scopelint
linters-settings: linters-settings:
gosec: # gosec:
excludes: # excludes:
- G204 # - G204
# gomnd: gomnd:
# settings: settings:
# mnd: mnd:
# ignored-functions: math.* ignored-functions: math.*
issues: issues:
exclude-rules: exclude-rules:
@ -45,4 +107,5 @@ issues:
linters: linters:
- errcheck - errcheck
- gosec - gosec
- maligned # Enable autofix
fix: true

3
go.mod
View File

@ -2,11 +2,12 @@ module git.iamthefij.com/iamthefij/restic-scheduler
go 1.17 go 1.17
require github.com/hashicorp/hcl/v2 v2.11.1
require ( require (
github.com/agext/levenshtein v1.2.1 // indirect github.com/agext/levenshtein v1.2.1 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/google/go-cmp v0.3.1 // indirect github.com/google/go-cmp v0.3.1 // indirect
github.com/hashicorp/hcl/v2 v2.11.1 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/zclconf/go-cty v1.8.0 // indirect github.com/zclconf/go-cty v1.8.0 // indirect
golang.org/x/text v0.3.5 // indirect golang.org/x/text v0.3.5 // indirect

6
go.sum
View File

@ -5,7 +5,9 @@ github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -14,13 +16,17 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/hashicorp/hcl/v2 v2.11.1 h1:yTyWcXcm9XB0TEkyU/JCRU6rYy4K+mgLtzn2wlrJbcc= github.com/hashicorp/hcl/v2 v2.11.1 h1:yTyWcXcm9XB0TEkyU/JCRU6rYy4K+mgLtzn2wlrJbcc=
github.com/hashicorp/hcl/v2 v2.11.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= github.com/hashicorp/hcl/v2 v2.11.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=

40
job.go
View File

@ -16,7 +16,7 @@ type TaskConfig struct {
Restic *ResticCmd Restic *ResticCmd
} }
// ResticConfig is all configuration to be sent to Restic // ResticConfig is all configuration to be sent to Restic.
type ResticConfig struct { type ResticConfig struct {
Repo string `hcl:"repo"` Repo string `hcl:"repo"`
Passphrase string `hcl:"passphrase,optional"` Passphrase string `hcl:"passphrase,optional"`
@ -24,14 +24,14 @@ type ResticConfig struct {
GlobalOpts *ResticGlobalOpts `hcl:"options,block"` GlobalOpts *ResticGlobalOpts `hcl:"options,block"`
} }
// ExecutableTask is a task to be run before or after backup/retore // ExecutableTask is a task to be run before or after backup/retore.
type ExecutableTask interface { type ExecutableTask interface {
RunBackup(cfg TaskConfig) error RunBackup(cfg TaskConfig) error
RunRestore(cfg TaskConfig) error RunRestore(cfg TaskConfig) error
Name() string Name() string
} }
// JobTaskScript is a sript to be executed as part of a job task // JobTaskScript is a sript to be executed as part of a job task.
type JobTaskScript struct { type JobTaskScript struct {
OnBackup string `hcl:"on_backup,optional"` OnBackup string `hcl:"on_backup,optional"`
OnRestore string `hcl:"on_restore,optional"` OnRestore string `hcl:"on_restore,optional"`
@ -40,7 +40,7 @@ type JobTaskScript struct {
name string name string
} }
// RunBackup runs script on backup // RunBackup runs script on backup.
func (t JobTaskScript) RunBackup(cfg TaskConfig) error { func (t JobTaskScript) RunBackup(cfg TaskConfig) error {
env := MergeEnv(cfg.Env, t.env) env := MergeEnv(cfg.Env, t.env)
if env == nil { if env == nil {
@ -61,7 +61,7 @@ func (t JobTaskScript) RunBackup(cfg TaskConfig) error {
return nil return nil
} }
// RunRestore script on restore // RunRestore script on restore.
func (t JobTaskScript) RunRestore(cfg TaskConfig) error { func (t JobTaskScript) RunRestore(cfg TaskConfig) error {
env := MergeEnv(cfg.Env, t.env) env := MergeEnv(cfg.Env, t.env)
if env == nil { if env == nil {
@ -90,7 +90,7 @@ func (t *JobTaskScript) SetName(name string) {
t.name = name t.name = name
} }
// JobTaskMySQL is a sqlite backup task that performs required pre and post tasks // JobTaskMySQL is a sqlite backup task that performs required pre and post tasks.
type JobTaskMySQL struct { type JobTaskMySQL struct {
Name string `hcl:"name,label"` Name string `hcl:"name,label"`
Hostname string `hcl:"hostname,optional"` Hostname string `hcl:"hostname,optional"`
@ -102,6 +102,7 @@ type JobTaskMySQL struct {
func (t JobTaskMySQL) GetPreTask() ExecutableTask { func (t JobTaskMySQL) GetPreTask() ExecutableTask {
return JobTaskScript{ return JobTaskScript{
name: t.Name, name: t.Name,
env: nil,
OnBackup: fmt.Sprintf( OnBackup: fmt.Sprintf(
"mysqldump -h '%s' -u '%s' -p '%s' '%s' > './%s.sql'", "mysqldump -h '%s' -u '%s' -p '%s' '%s' > './%s.sql'",
t.Hostname, t.Hostname,
@ -110,6 +111,7 @@ func (t JobTaskMySQL) GetPreTask() ExecutableTask {
t.Database, t.Database,
t.Name, t.Name,
), ),
OnRestore: "",
FromJobDir: true, FromJobDir: true,
} }
} }
@ -117,6 +119,8 @@ func (t JobTaskMySQL) GetPreTask() ExecutableTask {
func (t JobTaskMySQL) GetPostTask() ExecutableTask { func (t JobTaskMySQL) GetPostTask() ExecutableTask {
return JobTaskScript{ return JobTaskScript{
name: t.Name, name: t.Name,
env: nil,
OnBackup: "",
OnRestore: fmt.Sprintf( OnRestore: fmt.Sprintf(
"mysql -h '%s' -u '%s' -p '%s' '%s' << './%s.sql'", "mysql -h '%s' -u '%s' -p '%s' '%s' << './%s.sql'",
t.Hostname, t.Hostname,
@ -129,7 +133,7 @@ func (t JobTaskMySQL) GetPostTask() ExecutableTask {
} }
} }
// JobTaskSqlite is a sqlite backup task that performs required pre and post tasks // JobTaskSqlite is a sqlite backup task that performs required pre and post tasks.
type JobTaskSqlite struct { type JobTaskSqlite struct {
Name string `hcl:"name,label"` Name string `hcl:"name,label"`
Path string `hcl:"path"` Path string `hcl:"path"`
@ -138,17 +142,23 @@ type JobTaskSqlite struct {
func (t JobTaskSqlite) GetPreTask() ExecutableTask { func (t JobTaskSqlite) GetPreTask() ExecutableTask {
return JobTaskScript{ return JobTaskScript{
name: t.Name, name: t.Name,
env: nil,
OnBackup: fmt.Sprintf( OnBackup: fmt.Sprintf(
"sqlite3 %s '.backup $RESTIC_JOB_DIR/%s.bak'", "sqlite3 %s '.backup $RESTIC_JOB_DIR/%s.bak'",
t.Path, t.Name, t.Path, t.Name,
), ),
OnRestore: "",
FromJobDir: false,
} }
} }
func (t JobTaskSqlite) GetPostTask() ExecutableTask { func (t JobTaskSqlite) GetPostTask() ExecutableTask {
return JobTaskScript{ return JobTaskScript{
name: t.Name, name: t.Name,
env: nil,
OnBackup: "",
OnRestore: fmt.Sprintf("cp '$RESTIC_JOB_DIR/%s.bak' '%s'", t.Name, t.Path), OnRestore: fmt.Sprintf("cp '$RESTIC_JOB_DIR/%s.bak' '%s'", t.Name, t.Path),
FromJobDir: false,
} }
} }
@ -189,7 +199,7 @@ func (t *BackupFilesTask) SetName(name string) {
t.name = name t.name = name
} }
// JobTask represents a single task within a backup job // JobTask represents a single task within a backup job.
type JobTask struct { type JobTask struct {
Name string `hcl:"name,label"` Name string `hcl:"name,label"`
Scripts []JobTaskScript `hcl:"script,block"` Scripts []JobTaskScript `hcl:"script,block"`
@ -213,7 +223,7 @@ func (t JobTask) GetTasks() []ExecutableTask {
} }
// Job contains all configuration required to construct and run a backup // Job contains all configuration required to construct and run a backup
// and restore job // and restore job.
type Job struct { type Job struct {
Name string `hcl:"name,label"` Name string `hcl:"name,label"`
Schedule string `hcl:"schedule"` Schedule string `hcl:"schedule"`
@ -223,7 +233,7 @@ type Job struct {
Forget *ForgetOpts `hcl:"forget,block"` Forget *ForgetOpts `hcl:"forget,block"`
// Meta Tasks // Meta Tasks
MySql []JobTaskMySQL `hcl:"mysql,block"` MySQL []JobTaskMySQL `hcl:"mysql,block"`
Sqlite []JobTaskSqlite `hcl:"sqlite,block"` Sqlite []JobTaskSqlite `hcl:"sqlite,block"`
} }
@ -231,7 +241,7 @@ func (j Job) AllTasks() []ExecutableTask {
allTasks := []ExecutableTask{} allTasks := []ExecutableTask{}
// Pre tasks // Pre tasks
for _, mysql := range j.MySql { for _, mysql := range j.MySQL {
allTasks = append(allTasks, mysql.GetPreTask()) allTasks = append(allTasks, mysql.GetPreTask())
} }
@ -245,7 +255,7 @@ func (j Job) AllTasks() []ExecutableTask {
} }
// Post tasks // Post tasks
for _, mysql := range j.MySql { for _, mysql := range j.MySQL {
allTasks = append(allTasks, mysql.GetPreTask()) allTasks = append(allTasks, mysql.GetPreTask())
} }
@ -277,6 +287,7 @@ func (j Job) RunTasks() error {
JobDir: jobDir, JobDir: jobDir,
Logger: GetChildLogger(logger, exTask.Name()), Logger: GetChildLogger(logger, exTask.Name()),
Restic: restic, Restic: restic,
Env: nil,
} }
if err := exTask.RunBackup(taskCfg); err != nil { if err := exTask.RunBackup(taskCfg); err != nil {
@ -285,7 +296,9 @@ func (j Job) RunTasks() error {
} }
if j.Forget != nil { if j.Forget != nil {
restic.Forget(j.Forget) if err := restic.Forget(j.Forget); err != nil {
return fmt.Errorf("failed forgetting and pruning job %s: %w", j.Name, err)
}
} }
return nil return nil
@ -298,6 +311,7 @@ func (j Job) NewRestic() *ResticCmd {
Env: j.Config.Env, Env: j.Config.Env,
Passphrase: j.Config.Passphrase, Passphrase: j.Config.Passphrase,
GlobalOpts: j.Config.GlobalOpts, GlobalOpts: j.Config.GlobalOpts,
Cwd: "",
} }
} }

View File

@ -9,7 +9,7 @@ import (
) )
var ( var (
// version of restic-scheduler being run // version of restic-scheduler being run.
version = "dev" version = "dev"
) )

View File

@ -15,7 +15,7 @@ type CommandOptions interface {
type NoOpts struct{} type NoOpts struct{}
func (_ NoOpts) ToArgs() []string { func (NoOpts) ToArgs() []string {
return []string{} return []string{}
} }
@ -23,7 +23,7 @@ type ResticGlobalOpts struct {
CaCertFile string `hcl:"CaCertFile,optional"` CaCertFile string `hcl:"CaCertFile,optional"`
CacheDir string `hcl:"CacheDir,optional"` CacheDir string `hcl:"CacheDir,optional"`
PasswordFile string `hcl:"PasswordFile,optional"` PasswordFile string `hcl:"PasswordFile,optional"`
TlsClientCertFile string `hcl:"TlsClientCertFile,optional"` TLSClientCertFile string `hcl:"TlsClientCertFile,optional"`
LimitDownload int `hcl:"LimitDownload,optional"` LimitDownload int `hcl:"LimitDownload,optional"`
LimitUpload int `hcl:"LimitUpload,optional"` LimitUpload int `hcl:"LimitUpload,optional"`
VerboseLevel int `hcl:"VerboseLevel,optional"` VerboseLevel int `hcl:"VerboseLevel,optional"`
@ -32,6 +32,7 @@ type ResticGlobalOpts struct {
NoLock bool `hcl:"NoLock,optional"` NoLock bool `hcl:"NoLock,optional"`
} }
// nolint:cyclop
func (glo ResticGlobalOpts) ToArgs() (args []string) { func (glo ResticGlobalOpts) ToArgs() (args []string) {
if glo.CaCertFile != "" { if glo.CaCertFile != "" {
args = append(args, "--cacert", glo.CaCertFile) args = append(args, "--cacert", glo.CaCertFile)
@ -65,8 +66,8 @@ func (glo ResticGlobalOpts) ToArgs() (args []string) {
args = append(args, "--password-file", glo.PasswordFile) args = append(args, "--password-file", glo.PasswordFile)
} }
if glo.TlsClientCertFile != "" { if glo.TLSClientCertFile != "" {
args = append(args, "--tls-client-cert", glo.TlsClientCertFile) args = append(args, "--tls-client-cert", glo.TLSClientCertFile)
} }
if glo.VerboseLevel > 0 { if glo.VerboseLevel > 0 {
@ -120,9 +121,11 @@ func (rcmd ResticCmd) RunRestic(command string, options CommandOptions, commandA
cmd.Env = rcmd.BuildEnv() cmd.Env = rcmd.BuildEnv()
cmd.Dir = rcmd.Cwd cmd.Dir = rcmd.Cwd
err := cmd.Run() if err := cmd.Run(); err != nil {
return fmt.Errorf("error running restic: %w", err)
}
return err return nil
} }
type BackupOpts struct { type BackupOpts struct {
@ -146,7 +149,7 @@ func (bo BackupOpts) ToArgs() (args []string) {
func (rcmd ResticCmd) Backup(files []string, options *BackupOpts) error { func (rcmd ResticCmd) Backup(files []string, options *BackupOpts) error {
if options == nil { if options == nil {
options = &BackupOpts{} options = &BackupOpts{} // nolint:exhaustivestruct
} }
err := rcmd.RunRestic("backup", options, files...) err := rcmd.RunRestic("backup", options, files...)
@ -198,7 +201,7 @@ func (ro RestoreOpts) ToArgs() (args []string) {
func (rcmd ResticCmd) Restore(snapshot string, opts *RestoreOpts) error { func (rcmd ResticCmd) Restore(snapshot string, opts *RestoreOpts) error {
if opts == nil { if opts == nil {
opts = &RestoreOpts{} opts = &RestoreOpts{} // nolint:exhaustivestruct
} }
err := rcmd.RunRestic("restore", opts, snapshot) err := rcmd.RunRestic("restore", opts, snapshot)
@ -227,6 +230,7 @@ type ForgetOpts struct {
Prune bool `hcl:"Prune,optional"` Prune bool `hcl:"Prune,optional"`
} }
// nolint:funlen,cyclop
func (fo ForgetOpts) ToArgs() (args []string) { func (fo ForgetOpts) ToArgs() (args []string) {
// Add keep-* // Add keep-*
if fo.KeepLast > 0 { if fo.KeepLast > 0 {
@ -298,7 +302,7 @@ func (fo ForgetOpts) ToArgs() (args []string) {
func (rcmd ResticCmd) Forget(forgetOpts *ForgetOpts) error { func (rcmd ResticCmd) Forget(forgetOpts *ForgetOpts) error {
if forgetOpts == nil { if forgetOpts == nil {
forgetOpts = &ForgetOpts{} forgetOpts = &ForgetOpts{} // nolint:exhaustivestruct
} }
err := rcmd.RunRestic("forget", forgetOpts) err := rcmd.RunRestic("forget", forgetOpts)

View File

@ -30,25 +30,25 @@ func GetChildLogger(parent *log.Logger, name string) *log.Logger {
return GetLogger(childName) return GetLogger(childName)
} }
type logWriter struct { type LogWriter struct {
logger *log.Logger logger *log.Logger
} }
func NewLogWriter(logger *log.Logger) *logWriter { func NewLogWriter(logger *log.Logger) *LogWriter {
return &logWriter{logger} return &LogWriter{logger}
} }
func (w logWriter) Write(p []byte) (n int, err error) { func (w LogWriter) Write(content []byte) (n int, err error) {
message := fmt.Sprintf("%s", p) message := string(content)
for _, line := range strings.Split(message, "\n") { for _, line := range strings.Split(message, "\n") {
w.logger.Printf(" %s", line) w.logger.Printf(" %s", line)
} }
return len(p), nil return len(content), nil
} }
func RunShell(script string, cwd string, env map[string]string, logger *log.Logger) error { func RunShell(script string, cwd string, env map[string]string, logger *log.Logger) error {
cmd := exec.Command("sh", "-c", strings.TrimSpace(script)) cmd := exec.Command("sh", "-c", strings.TrimSpace(script)) // nolint:gosec
// Make both stderr and stdout go to logger // Make both stderr and stdout go to logger
// fmt.Println("LOGGER PREFIX", logger.Prefix()) // fmt.Println("LOGGER PREFIX", logger.Prefix())

View File

@ -1,6 +1,8 @@
package main package main
func MergeEnv(parent, child map[string]string) (result map[string]string) { func MergeEnv(parent, child map[string]string) map[string]string {
result := map[string]string{}
for key, value := range parent { for key, value := range parent {
result[key] = value result[key] = value
} }
@ -9,5 +11,5 @@ func MergeEnv(parent, child map[string]string) (result map[string]string) {
result[key] = value result[key] = value
} }
return return result
} }