From 3ed576faedc73c363c1ea19750baafd483ed17ff Mon Sep 17 00:00:00 2001 From: pardallio Date: Wed, 15 Jul 2026 12:37:37 +0000 Subject: [PATCH 1/4] fix: update argument parser for output file option in ecbundle-merge --- bin/ecbundle-merge | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/ecbundle-merge b/bin/ecbundle-merge index 86deec0..be2771f 100755 --- a/bin/ecbundle-merge +++ b/bin/ecbundle-merge @@ -44,7 +44,7 @@ def main(): nargs='+') - parser.add_argument('-o', + parser.add_argument('--output','-o', help='output file', default="merged-bundle.yml") # -------------------------------------------------------------------------- From 84659be29b4234fe822f2cfc343d22a6fb718221 Mon Sep 17 00:00:00 2001 From: pardallio Date: Wed, 15 Jul 2026 12:38:27 +0000 Subject: [PATCH 2/4] fix: enhance deep_merge to support erasing keys from original dictionary --- ecbundle/merge.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ecbundle/merge.py b/ecbundle/merge.py index 8369926..30897d1 100644 --- a/ecbundle/merge.py +++ b/ecbundle/merge.py @@ -34,12 +34,15 @@ def deep_merge(self, original, updates): if isinstance(original, dict) and isinstance(updates, dict): merged = copy.deepcopy(original) for key, value in updates.items(): + if isinstance(value, dict) and value.get("erase",False): + merged.pop(key,None) + continue if key in merged: if isinstance(merged[key], dict) and isinstance(value, dict): merged[key] = self.deep_merge(merged[key], value) else: merged[key] = copy.deepcopy(value) - else: + elif key!="erase": merged[key] = copy.deepcopy(value) return merged From f2702df685f6f7e2ad535161bda206fa116a3b1d Mon Sep 17 00:00:00 2001 From: pardallio Date: Wed, 15 Jul 2026 12:38:42 +0000 Subject: [PATCH 3/4] test: add test for merging with single erase update --- tests/bundle_merge/bundle-merge-erase.yml | 6 ++++++ tests/bundle_merge/test_merge.py | 14 ++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/bundle_merge/bundle-merge-erase.yml diff --git a/tests/bundle_merge/bundle-merge-erase.yml b/tests/bundle_merge/bundle-merge-erase.yml new file mode 100644 index 0000000..536d649 --- /dev/null +++ b/tests/bundle_merge/bundle-merge-erase.yml @@ -0,0 +1,6 @@ +projects : + + - project1 : + erase : true + + \ No newline at end of file diff --git a/tests/bundle_merge/test_merge.py b/tests/bundle_merge/test_merge.py index 3596077..bcca372 100644 --- a/tests/bundle_merge/test_merge.py +++ b/tests/bundle_merge/test_merge.py @@ -55,6 +55,20 @@ def test_merge_single_update(here, out_dir): assert "updated-branch" in content +def test_merge_single_erase(here, out_dir): + """Original bundle merged with a single update file.""" + base = here / "bundle-merge-base.yml" + upd = here / "bundle-merge-erase.yml" + output = out_dir / "merged.yml" + + rc = BundleMerger(**_args([base, upd], output)).merge() + + assert rc == 0 + assert output.exists() + content = output.read_text() + assert "project1" not in content + + def test_merge_multiple_updates_applied_in_order(here, out_dir): """With two updates, the later one wins on conflicting fields.""" base = here / "bundle-merge-base.yml" From d2cb0fc77d260e99a963d5171a58f4d597a53432 Mon Sep 17 00:00:00 2001 From: pardallio Date: Wed, 15 Jul 2026 13:31:24 +0000 Subject: [PATCH 4/4] lining --- ecbundle/merge.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ecbundle/merge.py b/ecbundle/merge.py index 30897d1..be278fa 100644 --- a/ecbundle/merge.py +++ b/ecbundle/merge.py @@ -34,15 +34,15 @@ def deep_merge(self, original, updates): if isinstance(original, dict) and isinstance(updates, dict): merged = copy.deepcopy(original) for key, value in updates.items(): - if isinstance(value, dict) and value.get("erase",False): - merged.pop(key,None) + if isinstance(value, dict) and value.get("erase", False): + merged.pop(key, None) continue if key in merged: if isinstance(merged[key], dict) and isinstance(value, dict): merged[key] = self.deep_merge(merged[key], value) else: merged[key] = copy.deepcopy(value) - elif key!="erase": + elif key != "erase": merged[key] = copy.deepcopy(value) return merged