Skip to content

Commit a72f635

Browse files
committed
Only pass common CLI args to command hooks [#100]
1 parent ea52e93 commit a72f635

File tree

2 files changed

+83
-9
lines changed

2 files changed

+83
-9
lines changed

wrapper.go

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"os"
88
"os/exec"
99
"path/filepath"
10+
"sort"
1011
"strings"
1112
"time"
1213

@@ -206,12 +207,57 @@ func (r *resticWrapper) runProfile() error {
206207
return nil
207208
}
208209

209-
func (r *resticWrapper) prepareCommand(command string, args *shell.Args) shellCommandDefinition {
210+
var commonResticArgsList = []string{
211+
"--cacert",
212+
"--cache-dir",
213+
"--cleanup-cache",
214+
"-h", "--help",
215+
"--insecure-tls",
216+
"--json",
217+
"--key-hint",
218+
"--limit-download",
219+
"--limit-upload",
220+
"--no-cache",
221+
"-o", "--option",
222+
"--password-command",
223+
"-p", "--password-file",
224+
"-q", "--quiet",
225+
"-r", "--repo",
226+
"--repository-file",
227+
"--tls-client-cert",
228+
"-v", "--verbose",
229+
}
230+
231+
// commonResticArgs turns args into commonArgs containing only those args that all restic commands understand
232+
func (r *resticWrapper) commonResticArgs(args []string) (commonArgs []string) {
233+
if !sort.StringsAreSorted(commonResticArgsList) {
234+
sort.Strings(commonResticArgsList)
235+
}
236+
skipValue := true
237+
238+
for _, arg := range args {
239+
if strings.HasPrefix(arg, "-") {
240+
lookup := strings.TrimSpace(strings.Split(arg, "=")[0])
241+
index := sort.SearchStrings(commonResticArgsList, lookup)
242+
if index < len(commonResticArgsList) && commonResticArgsList[index] == lookup {
243+
commonArgs = append(commonArgs, arg)
244+
skipValue = strings.Contains(arg, "=")
245+
continue
246+
}
247+
} else if !skipValue {
248+
commonArgs = append(commonArgs, arg)
249+
}
250+
skipValue = true
251+
}
252+
return
253+
}
254+
255+
func (r *resticWrapper) prepareCommand(command string, args *shell.Args, moreArgs ...string) shellCommandDefinition {
210256
// Create local instance to allow modification
211257
args = args.Clone()
212258

213-
if r.moreArgs != nil && len(r.moreArgs) > 0 {
214-
args.AddArgs(r.moreArgs, shell.ArgCommandLineEscape)
259+
if len(moreArgs) > 0 {
260+
args.AddArgs(moreArgs, shell.ArgCommandLineEscape)
215261
}
216262

217263
// Special case for backup command
@@ -245,7 +291,7 @@ func (r *resticWrapper) prepareCommand(command string, args *shell.Args) shellCo
245291
func (r *resticWrapper) runInitialize() error {
246292
clog.Infof("profile '%s': initializing repository (if not existing)", r.profile.Name)
247293
args := r.profile.GetCommandFlags(constants.CommandInit)
248-
rCommand := r.prepareCommand(constants.CommandInit, args)
294+
rCommand := r.prepareCommand(constants.CommandInit, args, r.commonResticArgs(r.moreArgs)...)
249295
// don't display any error
250296
rCommand.stderr = nil
251297
_, stderr, err := runShellCommand(rCommand)
@@ -262,7 +308,7 @@ func (r *resticWrapper) runInitializeCopy() error {
262308
// the copy command adds a 2 behind each flag about the secondary repository
263309
// in the case of init, we want to promote the secondary repository as primary
264310
args.PromoteSecondaryToPrimary()
265-
rCommand := r.prepareCommand(constants.CommandInit, args)
311+
rCommand := r.prepareCommand(constants.CommandInit, args, r.commonResticArgs(r.moreArgs)...)
266312
// don't display any error
267313
rCommand.stderr = nil
268314
_, stderr, err := runShellCommand(rCommand)
@@ -276,7 +322,7 @@ func (r *resticWrapper) runCheck() error {
276322
clog.Infof("profile '%s': checking repository consistency", r.profile.Name)
277323
args := r.profile.GetCommandFlags(constants.CommandCheck)
278324
for {
279-
rCommand := r.prepareCommand(constants.CommandCheck, args)
325+
rCommand := r.prepareCommand(constants.CommandCheck, args, r.commonResticArgs(r.moreArgs)...)
280326
summary, stderr, err := runShellCommand(rCommand)
281327
r.executionTime += summary.Duration
282328
r.summary(constants.CommandCheck, summary, stderr, err)
@@ -294,7 +340,7 @@ func (r *resticWrapper) runRetention() error {
294340
clog.Infof("profile '%s': cleaning up repository using retention information", r.profile.Name)
295341
args := r.profile.GetRetentionFlags()
296342
for {
297-
rCommand := r.prepareCommand(constants.CommandForget, args)
343+
rCommand := r.prepareCommand(constants.CommandForget, args, r.commonResticArgs(r.moreArgs)...)
298344
summary, stderr, err := runShellCommand(rCommand)
299345
r.executionTime += summary.Duration
300346
r.summary(constants.SectionConfigurationRetention, summary, stderr, err)
@@ -312,7 +358,7 @@ func (r *resticWrapper) runCommand(command string) error {
312358
clog.Infof("profile '%s': starting '%s'", r.profile.Name, command)
313359
args := r.profile.GetCommandFlags(command)
314360
for {
315-
rCommand := r.prepareCommand(command, args)
361+
rCommand := r.prepareCommand(command, args, r.moreArgs...)
316362

317363
if command == constants.CommandBackup && len(r.progress) > 0 {
318364
if r.profile.Backup != nil {
@@ -344,7 +390,7 @@ func (r *resticWrapper) runCommand(command string) error {
344390
func (r *resticWrapper) runUnlock() error {
345391
clog.Infof("profile '%s': unlock stale locks", r.profile.Name)
346392
args := r.profile.GetCommandFlags(constants.CommandUnlock)
347-
rCommand := r.prepareCommand(constants.CommandUnlock, args)
393+
rCommand := r.prepareCommand(constants.CommandUnlock, args, r.commonResticArgs(r.moreArgs)...)
348394
summary, stderr, err := runShellCommand(rCommand)
349395
r.executionTime += summary.Duration
350396
r.summary(constants.CommandUnlock, summary, stderr, err)

wrapper_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"bytes"
55
"fmt"
6+
"math/rand"
67
"os"
78
"os/exec"
89
"path/filepath"
@@ -33,6 +34,33 @@ func init() {
3334
} else {
3435
mockBinary = "./mock"
3536
}
37+
38+
// Add params that need to be passed to the mock binary
39+
commonResticArgsList = append(commonResticArgsList, "--exit")
40+
}
41+
42+
func TestCommonResticArgs(t *testing.T) {
43+
wrapper := &resticWrapper{}
44+
for _, arg := range commonResticArgsList {
45+
var args []string
46+
list := []string{"-x", "-x=1", "-x 2 x=y", "--xxx", "--xxx=v", "--xxx k=v", arg, arg + "=1", arg + " ka=va"}
47+
48+
for i := 0; i < 20; i++ {
49+
rand.Shuffle(len(list), func(i, j int) { list[i], list[j] = list[j], list[i] })
50+
args = args[:0]
51+
for _, item := range list {
52+
args = append(args, strings.Split(item, " ")...)
53+
}
54+
55+
args = wrapper.commonResticArgs(args)
56+
57+
assert.Len(t, args, 4)
58+
assert.Subset(t, args, []string{arg, arg + "=1", "ka=va"})
59+
for _, item := range []string{"-x", "--xxx", "x=y", "k=v", "2"} {
60+
assert.NotContains(t, args, item)
61+
}
62+
}
63+
}
3664
}
3765

3866
func TestGetEmptyEnvironment(t *testing.T) {

0 commit comments

Comments
 (0)