bitferry 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/bitferry/cli.rb CHANGED
@@ -1,375 +1,376 @@
1
- require 'clamp'
2
- require 'bitferry'
3
- require 'io/console'
4
-
5
-
6
- Endpoint = %{
7
- The endpoint may be one of:
8
- * directory -- absolute or relative local directory (/data, ../source, c:\\data)
9
- * local:directory, :directory -- absolute local directory (:/data, local:c:\\data)
10
- * :tag:directory -- path relative to the intact volume matched by (partial) tag (:fa2c:source/data)
11
-
12
- The former case resolves specified directory againt an intact volume to make it volume-relative.
13
- It is an error if there is no intact volume that encompasses specified directory.
14
- The local: directory is left as is (not resolved against volumes).
15
- The :tag: directory is bound to the specified volume.
16
- }
17
-
18
-
19
- Encryption = %{
20
- The encryption mode is controlled by --encrypt or --decrypt options.
21
- The mandatory password will be read from the standard input channel (pipe or keyboard).
22
- }
23
-
24
-
25
- $process = nil
26
- $encryption = nil
27
- $include = []
28
- $exclude = []
29
-
30
-
31
- def ext_globs(exts) = exts.split(',').collect { |ext| "*.#{ext}" }
32
-
33
-
34
- def setup_task(x, include: true)
35
- x.option ['-i'], 'EXTS', 'Include file extensions (comma-separated list)', multivalued: true, attribute_name: :include_exts do |exts|
36
- $include << ext_globs(exts)
37
- end if include
38
- x.option ['-x'], 'EXTS', 'Exclude file extensions (comma-separated list)', multivalued: true, attribute_name: :exclude_exts do |exts|
39
- $exclude << ext_globs(exts)
40
- end
41
- x.option ['--include'], 'GLOBS', 'Include path specifications (comma-separated list)', multivalued: true, attribute_name: :include do |globs|
42
- $include << globs.split(',')
43
- end if include
44
- x.option ['--exclude'], 'GLOBS', 'Exclude path specifications (comma-separated list)', multivalued: true, attribute_name: :exclude do |globs|
45
- $exclude << globs.split(',')
46
- end
47
- end
48
-
49
-
50
- def setup_rclone_task(x)
51
- x.parameter 'SOURCE', 'Source endpoint specifier'
52
- x.parameter 'DESTINATION', 'Destination endpoint specifier'
53
- x.option '-e', :flag, 'Encrypt files in destination using default profile (alias for -E default)', attribute_name: :e do
54
- $encryption = Bitferry::Rclone::Encrypt
55
- $profile = :default
56
- end
57
- x.option '-d', :flag, 'Decrypt source files using default profile (alias for -D default)', attribute_name: :d do
58
- $encryption = Bitferry::Rclone::Decrypt
59
- $profile = :default
60
- end
61
- x.option '-u', :flag, 'Apply extended (unicode) encryption profile options (alias for -E extended / -D extended)', attribute_name: :u do
62
- $extended = true
63
- end
64
- x.option ['--process', '-X'], 'OPTIONS', 'Extra task processing profile/options' do |opts|
65
- $process = opts
66
- end
67
- x.option ['--encrypt', '-E'], 'OPTIONS', 'Encrypt files in destination using specified profile/options' do |opts|
68
- $encryption = Bitferry::Rclone::Encrypt
69
- $profile = opts
70
- end
71
- x.option ['--decrypt', '-D'], 'OPTIONS', 'Decrypt source files using specified profile/options' do |opts|
72
- $encryption = Bitferry::Rclone::Decrypt
73
- $profile = opts
74
- end
75
- setup_task(x)
76
- end
77
-
78
-
79
- def create_rclone_task(task, *args, **opts)
80
- task.new(*args,
81
- process: $process,
82
- encryption: $encryption&.new(obtain_password, process: $extended ? :extended : $profile),
83
- include: $include.flatten.uniq, exclude: $exclude.flatten.uniq,
84
- **opts
85
- )
86
- end
87
-
88
-
89
- def bitferry(&code)
90
- begin
91
- Bitferry.restore
92
- result = yield
93
- exit(Bitferry.commit && result ? 0 : 1)
94
- rescue => e
95
- Bitferry.log.fatal(e.message)
96
- exit(1)
97
- end
98
- end
99
-
100
-
101
- def obtain_password
102
- if $stdin.tty?
103
- p1 = IO.console.getpass 'Enter password:'
104
- p2 = IO.console.getpass 'Repeat password:'
105
- raise 'passwords do not match' unless p1 == p2
106
- p1
107
- else
108
- $stdin.readline.strip!
109
- end
110
- end
111
-
112
-
113
- Bitferry.log.level = Logger::DEBUG if $DEBUG
114
-
115
-
116
- Clamp do
117
-
118
-
119
- self.default_subcommand = 'show'
120
-
121
-
122
- option '--version', :flag, 'Print version' do
123
- puts Bitferry::VERSION
124
- exit
125
- end
126
-
127
-
128
- option ['--verbose', '-v'], :flag, 'Extensive logging' do
129
- Bitferry.verbosity = :verbose
130
- end
131
-
132
-
133
- option ['--quiet', '-q'], :flag, 'Disable logging' do
134
- Bitferry.verbosity = :quiet
135
- end
136
-
137
-
138
- option ['--dry-run', '-n'], :flag, 'Simulation mode (make no on-disk changes)' do
139
- Bitferry.simulate = true
140
- end
141
-
142
-
143
- subcommand ['show', 'info', 'i'], 'Print state' do
144
- def execute
145
- Bitferry.restore
146
- unless (xs = Bitferry::Volume.intact).empty?
147
- puts '# Intact volumes'
148
- puts
149
- xs.each do |volume|
150
- puts " #{volume.tag} #{volume.root}"
151
- end
152
- end
153
- unless (xs = Bitferry::Task.intact).empty?
154
- puts
155
- puts '# Intact tasks'
156
- puts
157
- xs.each do |task|
158
- puts " #{task.tag} #{task.show_status}"
159
- end
160
- end
161
- if !(xs = Bitferry::Task.stale).empty? && Bitferry.verbosity == :verbose
162
- puts
163
- puts '# Stale tasks'
164
- puts
165
- xs.each do |task|
166
- puts " #{task.tag} #{task.show_status}"
167
- end
168
- end
169
- end
170
- end
171
-
172
-
173
- subcommand ['create', 'c'], 'Create entity' do
174
-
175
-
176
- subcommand ['volume', 'v'], 'Create volume' do
177
- banner %{
178
- Create new volume in specified directory. Create directory if it does not exist.
179
- Refuse to overwrite existing volume storage unless --force is specified.
180
- }
181
- option '--force', :flag, 'Overwrite existing volume storage in target directory'
182
- parameter 'DIRECTORY', 'Target volume directory'
183
- def execute
184
- bitferry { Bitferry::Volume.new(directory, overwrite: force?) }
185
- end
186
- end
187
-
188
-
189
- subcommand ['task', 't'], 'Create task' do
190
-
191
-
192
- subcommand ['copy', 'c'], 'Create copy task' do
193
- banner %{
194
- Create source --> destination file copy task.
195
-
196
- The task operates recursively on two specified endpoints.
197
- This task unconditionally copies all source files overwriting existing files in destination.
198
-
199
- #{Endpoint}
200
-
201
- #{Encryption}
202
-
203
- This task employs the Rclone worker.
204
- }
205
- setup_rclone_task(self)
206
- def execute
207
- bitferry { create_rclone_task(Bitferry::Rclone::Copy, source, destination) }
208
- end
209
- end
210
-
211
-
212
- subcommand ['update', 'u'], 'Create update task' do
213
- banner %{
214
- Create source --> destination file update (freshen) task.
215
-
216
- The task operates recursively on two specified endpoints.
217
- This task copies newer source files while skipping unchanged files in destination.
218
-
219
- #{Endpoint}
220
-
221
- #{Encryption}
222
-
223
- This task employs the Rclone worker.
224
- }
225
- setup_rclone_task(self)
226
- def execute
227
- bitferry { create_rclone_task(Bitferry::Rclone::Update, source, destination) }
228
- end
229
- end
230
-
231
-
232
- subcommand ['synchronize', 'sync', 's'], 'Create one way sync task' do
233
- banner %{
234
- Create source --> destination one way file synchronization task.
235
-
236
- The task operates recursively on two specified endpoints.
237
- This task copies newer source files while skipping unchanged files in destination.
238
- Also, it deletes destination files which are non-existent in source.
239
-
240
- #{Endpoint}
241
-
242
- #{Encryption}
243
-
244
- This task employs the Rclone worker.
245
- }
246
- setup_rclone_task(self)
247
- def execute
248
- bitferry { create_rclone_task(Bitferry::Rclone::Synchronize, source, destination) }
249
- end
250
- end
251
-
252
-
253
- subcommand ['equalize', 'bisync', 'e'], 'Create two way sync task' do
254
- banner %{
255
- Create source <-> destination two way file synchronization task.
256
-
257
- The task operates recursively on two specified endpoints.
258
- This task retains only the most recent versions of files on both endpoints.
259
- Opon execution both endpoints are left identical.
260
-
261
- #{Endpoint}
262
-
263
- #{Encryption}
264
-
265
- This task employs the Rclone worker.
266
- }
267
- setup_rclone_task(self)
268
- def execute
269
- bitferry { create_rclone_task(Bitferry::Rclone::Equalize, source, destination) }
270
- end
271
- end
272
-
273
-
274
- subcommand ['backup', 'b'], 'Create backup task' do
275
- banner %{
276
- Create source --> repository incremental backup task.
277
- This task employs the Restic worker.
278
- }
279
- option '--force', :flag, 'Force overwriting existing repository' do $format = true end
280
- option ['--attach', '-a'], :flag, 'Attach to existing repository' do $format = false end
281
- option '-f', :flag, 'Apply default snapshot retention policy options (alias for -F default)', attribute_name: :f do $forget = :default end
282
- option '-c', :flag, 'Apply default repository checking options (alias for -C default)', attribute_name: :c do $check = :default end
283
- option ['--process', '-X'], 'OPTIONS', 'Extra task processing profile/options' do |opts| $process = opts end
284
- option ['--forget', '-F'], 'OPTIONS', 'Snapshot retention policy with profile/options' do |opts| $forget = opts end
285
- option ['--check', '-C'], 'OPTIONS', 'Repository checking with profile/options' do |opts| $check = opts end
286
- parameter 'SOURCE', 'Source endpoint specifier'
287
- parameter 'REPOSITORY', 'Destination repository endpoint specifier'
288
- setup_task(self, include: false)
289
- def execute
290
- bitferry {
291
- Bitferry::Restic::Backup.new(
292
- source, repository, obtain_password,
293
- format: $format,
294
- process: $process,
295
- check: $check,
296
- forget: $forget,
297
- exclude: $exclude.flatten.uniq
298
- )
299
- }
300
- end
301
- end
302
-
303
-
304
- subcommand ['restore', 'r'], 'Create restore task' do
305
- banner %{
306
- Create repository --> destination restore task.
307
- This task employs the Restic worker.
308
- }
309
- option ['--process', '-X'], 'OPTIONS', 'Extra task processing profile/options' do |opts| $process = opts end
310
- parameter 'REPOSITORY', 'Source repository endpoint specifier'
311
- parameter 'DESTINATION', 'Destination endpoint specifier'
312
- setup_task(self)
313
- def execute
314
- bitferry {
315
- Bitferry::Restic::Restore.new(
316
- destination, repository, obtain_password,
317
- process: $process,
318
- include: $include.flatten.uniq, exclude: $exclude.flatten.uniq
319
- )
320
- }
321
- end
322
- end
323
-
324
-
325
- end
326
-
327
-
328
- end
329
-
330
-
331
- subcommand ['delete', 'd'], 'Delete entity' do
332
-
333
-
334
- subcommand ['volume', 'v'], 'Delete volume' do
335
- banner %{
336
- Delete volumes matched by specified (partial) tags.
337
- There may be multiple tags but each tag must match at most one volume.
338
- This command deletes the volume storage file only with the rest of data left intact.
339
- }
340
- option '--wipe', :flag, 'Wipe target directory upon deletion'
341
- parameter 'TAG ...', 'Volume tags', attribute_name: :tags
342
- def execute
343
- bitferry { Bitferry::Volume.delete(*tags, wipe: wipe?) }
344
- end
345
- end
346
-
347
-
348
- subcommand ['task', 't'], 'Delete task' do
349
- banner %{
350
- Delete tasks matched by specified (partial) tags.
351
- There may be multiple tags but each tag must match at most one task.
352
- }
353
- parameter 'TAG ...', 'Task tags', attribute_name: :tags
354
- def execute
355
- bitferry { Bitferry::Task.delete(*tags) }
356
- end
357
- end
358
-
359
-
360
- end
361
-
362
-
363
- subcommand ['process', 'x'], 'Process tasks' do
364
- banner %{
365
- Process tasks matched by specified (partial) tags.
366
- If no tags are given, process all intact tasks.
367
- }
368
- parameter '[TAG] ...', 'Task tags', attribute_name: :tags
369
- def execute
370
- bitferry { Bitferry.process(*tags) }
371
- end
372
- end
373
-
374
-
375
- end
1
+ require 'clamp'
2
+ require 'bitferry'
3
+ require 'io/console'
4
+
5
+
6
+ Endpoint = %{
7
+ The endpoint may be one of:
8
+ * directory -- absolute or relative local directory (/data, ../source, c:\\data)
9
+ * local:directory, :directory -- absolute local directory (:/data, local:c:\\data)
10
+ * :tag:directory -- path relative to the intact volume matched by (partial) tag (:fa2c:source/data)
11
+
12
+ The former case resolves specified directory againt an intact volume to make it volume-relative.
13
+ It is an error if there is no intact volume that encompasses specified directory.
14
+ The local: directory is left as is (not resolved against volumes).
15
+ The :tag: directory is bound to the specified volume.
16
+ }
17
+
18
+
19
+ Encryption = %{
20
+ The encryption mode is controlled by --encrypt or --decrypt options.
21
+ The mandatory password will be read from the standard input channel (pipe or keyboard).
22
+ }
23
+
24
+
25
+ $process = nil
26
+ $encryption = nil
27
+ $include = []
28
+ $exclude = []
29
+
30
+
31
+ def ext_globs(exts) = exts.split(',').collect { |ext| "*.#{ext}" }
32
+
33
+
34
+ def setup_task(x, include: true)
35
+ x.option ['-i'], 'EXTS', 'Include file extensions (comma-separated list)', multivalued: true, attribute_name: :include_exts do |exts|
36
+ $include << ext_globs(exts)
37
+ end if include
38
+ x.option ['-x'], 'EXTS', 'Exclude file extensions (comma-separated list)', multivalued: true, attribute_name: :exclude_exts do |exts|
39
+ $exclude << ext_globs(exts)
40
+ end
41
+ x.option ['--include'], 'GLOBS', 'Include path specifications (comma-separated list)', multivalued: true, attribute_name: :include do |globs|
42
+ $include << globs.split(',')
43
+ end if include
44
+ x.option ['--exclude'], 'GLOBS', 'Exclude path specifications (comma-separated list)', multivalued: true, attribute_name: :exclude do |globs|
45
+ $exclude << globs.split(',')
46
+ end
47
+ end
48
+
49
+
50
+ def setup_rclone_task(x)
51
+ x.parameter 'SOURCE', 'Source endpoint specifier'
52
+ x.parameter 'DESTINATION', 'Destination endpoint specifier'
53
+ x.option '-e', :flag, 'Encrypt files in destination using default profile (alias for -E default)', attribute_name: :e do
54
+ $encryption = Bitferry::Rclone::Encrypt
55
+ $profile = :default
56
+ end
57
+ x.option '-d', :flag, 'Decrypt source files using default profile (alias for -D default)', attribute_name: :d do
58
+ $encryption = Bitferry::Rclone::Decrypt
59
+ $profile = :default
60
+ end
61
+ x.option '-u', :flag, 'Apply extended (unicode) encryption profile options (alias for -E extended / -D extended)', attribute_name: :u do
62
+ $extended = true
63
+ end
64
+ x.option ['--process', '-X'], 'OPTIONS', 'Extra task processing profile/options' do |opts|
65
+ $process = opts
66
+ end
67
+ x.option ['--encrypt', '-E'], 'OPTIONS', 'Encrypt files in destination using specified profile/options' do |opts|
68
+ $encryption = Bitferry::Rclone::Encrypt
69
+ $profile = opts
70
+ end
71
+ x.option ['--decrypt', '-D'], 'OPTIONS', 'Decrypt source files using specified profile/options' do |opts|
72
+ $encryption = Bitferry::Rclone::Decrypt
73
+ $profile = opts
74
+ end
75
+ setup_task(x)
76
+ end
77
+
78
+
79
+ def create_rclone_task(task, *args, **opts)
80
+ task.new(*args,
81
+ process: $process,
82
+ encryption: $encryption&.new(obtain_password, process: $extended ? :extended : $profile),
83
+ include: $include.flatten.uniq, exclude: $exclude.flatten.uniq,
84
+ **opts
85
+ )
86
+ end
87
+
88
+
89
+ def bitferry(&code)
90
+ begin
91
+ Bitferry.restore
92
+ result = yield
93
+ exit(Bitferry.commit && result ? 0 : 1)
94
+ rescue => e
95
+ Bitferry.log.fatal(e.message)
96
+ exit(1)
97
+ end
98
+ end
99
+
100
+
101
+ def obtain_password
102
+ if $stdin.tty?
103
+ p1 = IO.console.getpass 'Enter password:'
104
+ p2 = IO.console.getpass 'Repeat password:'
105
+ raise 'passwords do not match' unless p1 == p2
106
+ p1
107
+ else
108
+ $stdin.readline.strip!
109
+ end
110
+ end
111
+
112
+
113
+ Bitferry.ui = :cli
114
+ Bitferry.log.level = Logger::DEBUG if $DEBUG
115
+
116
+
117
+ Clamp do
118
+
119
+
120
+ self.default_subcommand = 'show'
121
+
122
+
123
+ option '--version', :flag, 'Print version' do
124
+ $stdout.puts Bitferry::VERSION
125
+ exit
126
+ end
127
+
128
+
129
+ option ['--verbose', '-v'], :flag, 'Extensive logging' do
130
+ Bitferry.verbosity = :verbose
131
+ end
132
+
133
+
134
+ option ['--quiet', '-q'], :flag, 'Disable logging' do
135
+ Bitferry.verbosity = :quiet
136
+ end
137
+
138
+
139
+ option ['--dry-run', '-n'], :flag, 'Simulation mode (make no on-disk changes)' do
140
+ Bitferry.simulate = true
141
+ end
142
+
143
+
144
+ subcommand ['show', 'info', 'i'], 'Print state' do
145
+ def execute
146
+ Bitferry.restore
147
+ unless (xs = Bitferry::Volume.intact).empty?
148
+ $stdout.puts '# Intact volumes'
149
+ $stdout.puts
150
+ xs.each do |volume|
151
+ $stdout.puts " #{volume.tag} #{volume.root}"
152
+ end
153
+ end
154
+ unless (xs = Bitferry::Task.intact).empty?
155
+ $stdout.puts
156
+ $stdout.puts '# Intact tasks'
157
+ $stdout.puts
158
+ xs.each do |task|
159
+ $stdout.puts " #{task.tag} #{task.show_status}"
160
+ end
161
+ end
162
+ if !(xs = Bitferry::Task.stale).empty? && Bitferry.verbosity == :verbose
163
+ $stdout.puts
164
+ $stdout.puts '# Stale tasks'
165
+ $stdout.puts
166
+ xs.each do |task|
167
+ $stdout.puts " #{task.tag} #{task.show_status}"
168
+ end
169
+ end
170
+ end
171
+ end
172
+
173
+
174
+ subcommand ['create', 'c'], 'Create entity' do
175
+
176
+
177
+ subcommand ['volume', 'v'], 'Create volume' do
178
+ banner %{
179
+ Create new volume in specified directory. Create directory if it does not exist.
180
+ Refuse to overwrite existing volume storage unless --force is specified.
181
+ }
182
+ option '--force', :flag, 'Overwrite existing volume storage in target directory'
183
+ parameter 'DIRECTORY', 'Target volume directory'
184
+ def execute
185
+ bitferry { Bitferry::Volume.new(directory, overwrite: force?) }
186
+ end
187
+ end
188
+
189
+
190
+ subcommand ['task', 't'], 'Create task' do
191
+
192
+
193
+ subcommand ['copy', 'c'], 'Create copy task' do
194
+ banner %{
195
+ Create source --> destination file copy task.
196
+
197
+ The task operates recursively on two specified endpoints.
198
+ This task unconditionally copies all source files overwriting existing files in destination.
199
+
200
+ #{Endpoint}
201
+
202
+ #{Encryption}
203
+
204
+ This task employs the Rclone worker.
205
+ }
206
+ setup_rclone_task(self)
207
+ def execute
208
+ bitferry { create_rclone_task(Bitferry::Rclone::Copy, source, destination) }
209
+ end
210
+ end
211
+
212
+
213
+ subcommand ['update', 'u'], 'Create update task' do
214
+ banner %{
215
+ Create source --> destination file update (freshen) task.
216
+
217
+ The task operates recursively on two specified endpoints.
218
+ This task copies newer source files while skipping unchanged files in destination.
219
+
220
+ #{Endpoint}
221
+
222
+ #{Encryption}
223
+
224
+ This task employs the Rclone worker.
225
+ }
226
+ setup_rclone_task(self)
227
+ def execute
228
+ bitferry { create_rclone_task(Bitferry::Rclone::Update, source, destination) }
229
+ end
230
+ end
231
+
232
+
233
+ subcommand ['synchronize', 'sync', 's'], 'Create one way sync task' do
234
+ banner %{
235
+ Create source --> destination one way file synchronization task.
236
+
237
+ The task operates recursively on two specified endpoints.
238
+ This task copies newer source files while skipping unchanged files in destination.
239
+ Also, it deletes destination files which are non-existent in source.
240
+
241
+ #{Endpoint}
242
+
243
+ #{Encryption}
244
+
245
+ This task employs the Rclone worker.
246
+ }
247
+ setup_rclone_task(self)
248
+ def execute
249
+ bitferry { create_rclone_task(Bitferry::Rclone::Synchronize, source, destination) }
250
+ end
251
+ end
252
+
253
+
254
+ subcommand ['equalize', 'bisync', 'e'], 'Create two way sync task' do
255
+ banner %{
256
+ Create source <-> destination two way file synchronization task.
257
+
258
+ The task operates recursively on two specified endpoints.
259
+ This task retains only the most recent versions of files on both endpoints.
260
+ Opon execution both endpoints are left identical.
261
+
262
+ #{Endpoint}
263
+
264
+ #{Encryption}
265
+
266
+ This task employs the Rclone worker.
267
+ }
268
+ setup_rclone_task(self)
269
+ def execute
270
+ bitferry { create_rclone_task(Bitferry::Rclone::Equalize, source, destination) }
271
+ end
272
+ end
273
+
274
+
275
+ subcommand ['backup', 'b'], 'Create backup task' do
276
+ banner %{
277
+ Create source --> repository incremental backup task.
278
+ This task employs the Restic worker.
279
+ }
280
+ option '--force', :flag, 'Force overwriting existing repository' do $format = true end
281
+ option ['--attach', '-a'], :flag, 'Attach to existing repository' do $format = false end
282
+ option '-f', :flag, 'Apply default snapshot retention policy options (alias for -F default)', attribute_name: :f do $forget = :default end
283
+ option '-c', :flag, 'Apply default repository checking options (alias for -C default)', attribute_name: :c do $check = :default end
284
+ option ['--process', '-X'], 'OPTIONS', 'Extra task processing profile/options' do |opts| $process = opts end
285
+ option ['--forget', '-F'], 'OPTIONS', 'Snapshot retention policy with profile/options' do |opts| $forget = opts end
286
+ option ['--check', '-C'], 'OPTIONS', 'Repository checking with profile/options' do |opts| $check = opts end
287
+ parameter 'SOURCE', 'Source endpoint specifier'
288
+ parameter 'REPOSITORY', 'Destination repository endpoint specifier'
289
+ setup_task(self, include: false)
290
+ def execute
291
+ bitferry {
292
+ Bitferry::Restic::Backup.new(
293
+ source, repository, obtain_password,
294
+ format: $format,
295
+ process: $process,
296
+ check: $check,
297
+ forget: $forget,
298
+ exclude: $exclude.flatten.uniq
299
+ )
300
+ }
301
+ end
302
+ end
303
+
304
+
305
+ subcommand ['restore', 'r'], 'Create restore task' do
306
+ banner %{
307
+ Create repository --> destination restore task.
308
+ This task employs the Restic worker.
309
+ }
310
+ option ['--process', '-X'], 'OPTIONS', 'Extra task processing profile/options' do |opts| $process = opts end
311
+ parameter 'REPOSITORY', 'Source repository endpoint specifier'
312
+ parameter 'DESTINATION', 'Destination endpoint specifier'
313
+ setup_task(self)
314
+ def execute
315
+ bitferry {
316
+ Bitferry::Restic::Restore.new(
317
+ destination, repository, obtain_password,
318
+ process: $process,
319
+ include: $include.flatten.uniq, exclude: $exclude.flatten.uniq
320
+ )
321
+ }
322
+ end
323
+ end
324
+
325
+
326
+ end
327
+
328
+
329
+ end
330
+
331
+
332
+ subcommand ['delete', 'd'], 'Delete entity' do
333
+
334
+
335
+ subcommand ['volume', 'v'], 'Delete volume' do
336
+ banner %{
337
+ Delete volumes matched by specified (partial) tags.
338
+ There may be multiple tags but each tag must match at most one volume.
339
+ This command deletes the volume storage file only with the rest of data left intact.
340
+ }
341
+ option '--wipe', :flag, 'Wipe target directory upon deletion'
342
+ parameter 'TAG ...', 'Volume tags', attribute_name: :tags
343
+ def execute
344
+ bitferry { Bitferry::Volume.delete(*tags, wipe: wipe?) }
345
+ end
346
+ end
347
+
348
+
349
+ subcommand ['task', 't'], 'Delete task' do
350
+ banner %{
351
+ Delete tasks matched by specified (partial) tags.
352
+ There may be multiple tags but each tag must match at most one task.
353
+ }
354
+ parameter 'TAG ...', 'Task tags', attribute_name: :tags
355
+ def execute
356
+ bitferry { Bitferry::Task.delete(*tags) }
357
+ end
358
+ end
359
+
360
+
361
+ end
362
+
363
+
364
+ subcommand ['process', 'x'], 'Process tasks' do
365
+ banner %{
366
+ Process tasks matched by specified (partial) tags.
367
+ If no tags are given, process all intact tasks.
368
+ }
369
+ parameter '[TAG] ...', 'Task tags', attribute_name: :tags
370
+ def execute
371
+ bitferry { Bitferry.process(*tags) }
372
+ end
373
+ end
374
+
375
+
376
+ end