@@ -3,11 +3,13 @@ package main
3
3
import (
4
4
"fmt"
5
5
"os"
6
+ "path/filepath"
6
7
"strings"
7
8
8
9
"github.com/creativeprojects/resticprofile/clog"
9
10
"github.com/creativeprojects/resticprofile/config"
10
11
"github.com/creativeprojects/resticprofile/constants"
12
+ "github.com/creativeprojects/resticprofile/lock"
11
13
)
12
14
13
15
type resticWrapper struct {
@@ -38,79 +40,88 @@ func newResticWrapper(
38
40
}
39
41
40
42
func (r * resticWrapper ) runProfile () error {
41
- if r .initialize && r .command != constants .CommandInit {
42
- _ = r .runInitialize ()
43
- // it's ok for the initialize to error out when the repository exists
44
- }
45
-
46
43
err := lockRun (r .profile .Lock , func () error {
47
- var err error
48
-
49
- // pre-profile commands
50
- err = r .runProfilePreCommand ()
51
- if err != nil {
52
- return err
53
- }
44
+ return runOnFailure (
45
+ func () error {
46
+ var err error
54
47
55
- // pre-commands (for backup)
56
- if r .command == constants .CommandBackup {
57
- // Shell commands
58
- err = r .runPreCommand (r .command )
59
- if err != nil {
60
- return err
61
- }
62
- // Check
63
- if r .profile .Backup != nil && r .profile .Backup .CheckBefore {
64
- err = r .runCheck ()
48
+ // pre-profile commands
49
+ err = r .runProfilePreCommand ()
65
50
if err != nil {
66
51
return err
67
52
}
68
- }
69
- // Retention
70
- if r . profile . Retention != nil && r . profile . Retention . BeforeBackup {
71
- err = r . runRetention ()
72
- if err != nil {
73
- return err
53
+
54
+ // breaking change from 0.7.0 and 0.7.1:
55
+ // run the initialization after the pre- profile commands
56
+ if r . initialize && r . command != constants . CommandInit {
57
+ _ = r . runInitialize ()
58
+ // it's ok for the initialize to error out when the repository exists
74
59
}
75
- }
76
- }
77
60
78
- // Main command
79
- err = r .runCommand (r .command )
80
- if err != nil {
81
- return err
82
- }
61
+ // pre-commands (for backup)
62
+ if r .command == constants .CommandBackup {
63
+ // Shell commands
64
+ err = r .runPreCommand (r .command )
65
+ if err != nil {
66
+ return err
67
+ }
68
+ // Check
69
+ if r .profile .Backup != nil && r .profile .Backup .CheckBefore {
70
+ err = r .runCheck ()
71
+ if err != nil {
72
+ return err
73
+ }
74
+ }
75
+ // Retention
76
+ if r .profile .Retention != nil && r .profile .Retention .BeforeBackup {
77
+ err = r .runRetention ()
78
+ if err != nil {
79
+ return err
80
+ }
81
+ }
82
+ }
83
83
84
- // post-commands (for backup)
85
- if r .command == constants .CommandBackup {
86
- // Retention
87
- if r .profile .Retention != nil && r .profile .Retention .AfterBackup {
88
- err = r .runRetention ()
84
+ // Main command
85
+ err = r .runCommand (r .command )
89
86
if err != nil {
90
87
return err
91
88
}
92
- }
93
- // Check
94
- if r .profile .Backup != nil && r .profile .Backup .CheckAfter {
95
- err = r .runCheck ()
89
+
90
+ // post-commands (for backup)
91
+ if r .command == constants .CommandBackup {
92
+ // Retention
93
+ if r .profile .Retention != nil && r .profile .Retention .AfterBackup {
94
+ err = r .runRetention ()
95
+ if err != nil {
96
+ return err
97
+ }
98
+ }
99
+ // Check
100
+ if r .profile .Backup != nil && r .profile .Backup .CheckAfter {
101
+ err = r .runCheck ()
102
+ if err != nil {
103
+ return err
104
+ }
105
+ }
106
+ // Shell commands
107
+ err = r .runPostCommand (r .command )
108
+ if err != nil {
109
+ return err
110
+ }
111
+ }
112
+
113
+ // post-profile commands
114
+ err = r .runProfilePostCommand ()
96
115
if err != nil {
97
116
return err
98
117
}
99
- }
100
- // Shell commands
101
- err = r .runPostCommand (r .command )
102
- if err != nil {
103
- return err
104
- }
105
- }
106
-
107
- // post-profile commands
108
- err = r .runProfilePostCommand ()
109
- if err != nil {
110
- return err
111
- }
112
118
113
- return nil
119
+ return nil
120
+ },
121
+ func () {
122
+ _ = r .runProfilePostFailCommand ()
123
+ },
124
+ )
114
125
})
115
126
if err != nil {
116
127
return err
@@ -312,3 +323,35 @@ func convertIntoArgs(flags map[string][]string) []string {
312
323
}
313
324
return args
314
325
}
326
+
327
+ // lockRun is making sure the function is only run once by putting a lockfile on the disk
328
+ func lockRun (filename string , run func () error ) error {
329
+ if filename == "" {
330
+ // No lock
331
+ return run ()
332
+ }
333
+ // Make sure the path to the lock exists
334
+ dir := filepath .Dir (filename )
335
+ if dir != "" {
336
+ err := os .MkdirAll (dir , 0755 )
337
+ if err != nil {
338
+ clog .Warningf ("The profile will run without a lockfile: %v" , err )
339
+ return run ()
340
+ }
341
+ }
342
+ runLock := lock .NewLock (filename )
343
+ if ! runLock .TryAcquire () {
344
+ return fmt .Errorf ("another process is already running this profile: %s" , runLock .Who ())
345
+ }
346
+ defer runLock .Release ()
347
+ return run ()
348
+ }
349
+
350
+ // runOnFailure will run the onFailure function if an error occurred in the run function
351
+ func runOnFailure (run func () error , onFailure func ()) error {
352
+ err := run ()
353
+ if err != nil {
354
+ onFailure ()
355
+ }
356
+ return err
357
+ }
0 commit comments