boom/command.py | 84 ++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 63 insertions(+), 21 deletions(-)
diff --git a/boom/command.py b/boom/command.py
index dc9abae..8900457 100644
--- a/boom/command.py
+++ b/boom/command.py
@@ -482,24 +482,72 @@ def _do_print_type(report_fields, selected, output_fields=None,
return br.report_output()
-def _merge_add_del_opts(orig_opts, opts):
+def _merge_add_del_opts(bp, add_opts, del_opts):
"""Merge a set of existing bootparams option alterations with
a set of command-line provided values to produce a single
set of options to add or remove from a cloned or edited
``BootEntry``.
- :param orig_opts: A list of original option modifications
- :param opts: A space-separated string containing a list of
- command line option modifications
- :returns: A single list containing the merged options
- """
- # Merge new and cloned kernel options
- all_opts = set()
- if opts:
- all_opts.update(opts.split())
- if orig_opts:
- all_opts.update(orig_opts)
- return list(all_opts)
+ The sets are merged giving precedence to alterations on the
+ current command line: i.e. if an option is present in both
+ ``bp.del_opts`` and ``add_opts`` (or vice versa) then the
+ option taken from the current command line will be effective.
+
+ :param bp: A ``BootParams`` object with the original ``add_opts``
+ and ``del_opts`` values.
+ :param add_opts: A space-separated string containing a list of
+ additional options taken from the current
+ command line.
+ :param del_opts: A space-separated string containing a list of
+ options to delete taken from the current
+ command line.
+ :returns: A tuple ``(effective_add_opts, effective_del_opts)``
+ giving the final effective values as a list of
+ strings, one per option word.
+ """
+ def _merge_opts(orig_opts, opts, r_opts):
+ # Merge new and cloned kernel options
+ all_opts = set()
+ if opts:
+ all_opts.update(opts)
+ if orig_opts:
+ all_opts.update(orig_opts)
+ all_opts = list(all_opts)
+ return [o for o in all_opts if o not in r_opts]
+
+ _log_debug_cmd("Add opts: %s" % add_opts)
+ _log_debug_cmd("Del opts: %s" % del_opts)
+ _log_debug_cmd("Original add_opts: %s" % bp.add_opts)
+ _log_debug_cmd("Original del_opts: %s" % bp.del_opts)
+
+ r_del_opts = []
+ r_add_opts = []
+
+ add_opts = add_opts.split() if add_opts else []
+ del_opts = del_opts.split() if del_opts else []
+
+ for add_opt in list(add_opts):
+ # Do not allow conflicting command line add/del opts
+ if add_opt in del_opts:
+ raise ValueError("Conflicting --add-opts %s and --del-opts %s" %
+ (add_opt, add_opt))
+
+ if add_opt in bp.del_opts:
+ r_del_opts.append(add_opt)
+ add_opts.remove(add_opt)
+
+ for del_opt in list(del_opts):
+ if del_opt in bp.add_opts:
+ r_add_opts.append(del_opt)
+ del_opts.remove(del_opt)
+
+ add_opts = _merge_opts(bp.add_opts, add_opts, r_add_opts)
+ del_opts = _merge_opts(bp.del_opts, del_opts, r_del_opts)
+
+ _log_debug_cmd("Effective add options: %s" % add_opts)
+ _log_debug_cmd("Effective del options: %s" % del_opts)
+
+ return (add_opts, del_opts)
#
@@ -759,10 +807,7 @@ def clone_entry(selection=None, title=None, version=None, machine_id=None,
else be.bp.btrfs_subvol_id)
profile = profile if profile else be._osp
- add_opts = _merge_add_del_opts(be.bp.add_opts, add_opts)
- del_opts = _merge_add_del_opts(be.bp.del_opts, del_opts)
- _log_debug_cmd("Effective add options: %s" % add_opts)
- _log_debug_cmd("Effective del options: %s" % del_opts)
+ (add_opts, del_opts) = _merge_add_del_opts(be.bp, add_opts, del_opts)
bp = BootParams(version, root_device, lvm_root_lv=lvm_root_lv,
btrfs_subvol_path=btrfs_subvol_path,
@@ -864,10 +909,7 @@ def edit_entry(selection=None, title=None, version=None, machine_id=None,
machine_id = machine_id or be.machine_id
version = version or be.version
- add_opts = _merge_add_del_opts(be.bp.add_opts, add_opts)
- del_opts = _merge_add_del_opts(be.bp.del_opts, del_opts)
- _log_debug_cmd("Effective add options: %s" % add_opts)
- _log_debug_cmd("Effective del options: %s" % del_opts)
+ (add_opts, del_opts) = _merge_add_del_opts(be.bp, add_opts, del_opts)
be._osp = profile or be._osp
be.title = title or be.title