Skip to content
This repository was archived by the owner on Jun 15, 2025. It is now read-only.

Commit b395b3e

Browse files
committed
Introduce --join option
This change marks the last step in the introduction of proper command execution in the form of springs. It adds a new option, --join, that, when used, causes different behavior in a couple of respects: 1) The way filters are executed and data is transferred between them changes. Previously, the execution model was always a pipeline. With this change, all filter commands listed before the --join option are interpreted as a spring, meaning that they will be executed in a serial fashion and the *accumulated* output will be passed to the commands following this option. 2) Handling of the special '{file}' string used for signalling btrfs-backup where in a command a file name is to be inserted is modified. Without --join, the behavior stays the same. That is, the (long) option (is any) accompanying this string is replicated for all the required files. Now, if --join is passed in (and it being placed behind some filter command), this string will cause the entire command containing the '{file}' string to be replicated for each file and added to the spring. On a high level, the purpose of this change is to enable support for the following scenario: There exists a file repository (possibly on a remote host). This repository already contains a set of snapshots (one full [and, hence, self-contained] one and more incremental ones). If a restore is desired from this file repository the data from all snapshots might be needed to restore the backed up state. Now, some programs (such as GnuPG which could be used for encryption in such a scenario) do not allow working with multiple files at once. To that end, multiple instances have to be started and their output needs to be accumulated before further processing can happen.
1 parent 17fbcd5 commit b395b3e

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed

btrfs-backup/src/deso/btrfs/main.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,26 @@ def addStandardArgs(parser):
175175

176176
def addOptionalArgs(parser, namespace, backup):
177177
"""Add the optional arguments to a parser."""
178+
parser.add_argument(
179+
# In order to implement the --join option we use a trick: Since we
180+
# cannot use a type field that performs an action for us as we do
181+
# for the reverse-hidden-helper option (because this option does not
182+
# accept an argument), we append the value 'None' to the
183+
# 'send_filters' array that stores all send filters.
184+
# TODO: Right now this option can be specified multiple times. That
185+
# is wrong and should not be allowed. However, it is tricky to
186+
# enforce that. Find a way.
187+
"--join", action="append_const", const=[None], dest="send_filters",
188+
help="Only allowed in conjunction with send filters. When specified, "\
189+
"it does two things. First, it changes the default execution "\
190+
"mode for the commands from a pipeline with a single source "\
191+
"(origin of data) to one with multiple sources. Which means "\
192+
"that the previous commands (filters) will be run in sequence "\
193+
"and their output be accumulated into a single destination "\
194+
"(rather than it being piped from one filter to the next). "\
195+
"Secondly, all subsequent filters will have the data from this "\
196+
"one source as their input.",
197+
)
178198
parser.add_argument(
179199
"--no-read-stderr", action="store_false", dest="read_err", default=True,
180200
help="Turn off reading of data from stderr. No information about "
@@ -344,6 +364,26 @@ def add_usage(self, usage, actions, groups, prefix=None):
344364

345365
def prepareNamespace(ns):
346366
"""Prepare the given namespace object for conversion into dict."""
367+
def split(filters):
368+
"""Split a number of filters into an array of commands."""
369+
return [f.split() for f in filters]
370+
371+
def prepare(filters):
372+
"""Prepare filters ready for use by the remaining parts of the program."""
373+
# The filters array might contain a None element (if the --join
374+
# option is used). In that case we set up the final array in a
375+
# different way: the first element will be an array of filters (as
376+
# opposed to a single filter).
377+
if None in filters:
378+
index = filters.index(None)
379+
part1 = split(filters[:index])
380+
part2 = split(filters[index+1:])
381+
382+
# Create a new array with the first element being an array itself.
383+
return [part1] + part2
384+
else:
385+
return split(filters)
386+
347387
command = ns.command
348388
src_repo = ns.src
349389
dst_repo = ns.dst
@@ -360,10 +400,15 @@ def prepareNamespace(ns):
360400
# spaces in their path. E.g., "/bin/connect to server" would
361401
# not be a valid command.
362402
remote_cmd = remote_cmd.split()
403+
404+
# Note that intuitively only the send filters can contain a None
405+
# element in case the --join option is supplied. However, in case we
406+
# have a --reverse option as well the filters could get swapped (which
407+
# always happens after the insertion of the empty element).
363408
if send_filters:
364-
send_filters = [filt.split() for filt in send_filters]
409+
send_filters = prepare(send_filters)
365410
if recv_filters:
366-
recv_filters = [filt.split() for filt in recv_filters]
411+
recv_filters = prepare(recv_filters)
367412

368413
ns.recv_filters = recv_filters
369414
ns.send_filters = send_filters

btrfs-backup/src/deso/btrfs/test/testMain.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ def runMain(*args):
174174
with self.assertRaisesRegex(ChildProcessError, regex):
175175
runMain("restore", "--snapshot-ext=gz", "--send-filter", "/bin/gzip")
176176

177+
# TODO: We should likely add a test to verify that the {file}
178+
# detection works in conjunction with springs and the --join
179+
# option.
180+
177181
# This call succeeds from the point of view of supplying the
178182
# snapshot-ext option but other arguments are missing so we still
179183
# bail out.

0 commit comments

Comments
 (0)