diff --git a/bin/homelab b/bin/homelab index 3df8d6a..09ada69 100755 --- a/bin/homelab +++ b/bin/homelab @@ -141,6 +141,10 @@ def _add_recipient_to_sops_policy(sops_path: Path, path_regex_pattern: str, pubk for i, line in enumerate(lines): stripped = line.strip() if stripped.startswith("- path_regex:"): + # If we've already collected what we need from the target rule, + # stop — don't let the next rule wipe age_block_last_idx. + if in_target_rule and age_block_last_idx is not None: + break in_target_rule = path_regex_pattern in line age_block_start = None age_block_last_idx = None @@ -152,13 +156,12 @@ def _add_recipient_to_sops_policy(sops_path: Path, path_regex_pattern: str, pubk continue if age_block_start is None: continue - # Inside the age block; track the last age1... line. if "age1" in stripped: if pubkey in line: return True # already a recipient age_block_last_idx = i elif stripped == "" or stripped.startswith("#"): - continue # blank / comment inside the block + continue else: break # next key, age block ended if age_block_last_idx is None: @@ -204,59 +207,47 @@ def _remove_recipient_from_sops_policy(sops_path: Path, path_regex_pattern: str, if not sops_path.exists(): return False lines = sops_path.read_text().splitlines(keepends=True) - in_target_rule = False - age_block_start = None - target_idx = None - for i, line in enumerate(lines): - stripped = line.strip() - if stripped.startswith("- path_regex:"): - in_target_rule = path_regex_pattern in line - age_block_start = None - target_idx = None - continue - if not in_target_rule: - continue - if "age: >-" in line: - age_block_start = i - continue - if age_block_start is None: - continue - if "age1" in stripped: - if pubkey in line: - target_idx = i + + def find_target_age_lines() -> tuple[list[int], bool]: + """Scan and return (indices_of_age1_lines_in_target_rule, found_rule).""" + in_target = False + age_block_start = None + age_idxs: list[int] = [] + for i, line in enumerate(lines): + stripped = line.strip() + if stripped.startswith("- path_regex:"): + if in_target and age_idxs: + return age_idxs, True + in_target = path_regex_pattern in line + age_block_start = None + age_idxs = [] + continue + if not in_target: + continue + if "age: >-" in line: + age_block_start = i + continue + if age_block_start is None: + continue + if "age1" in stripped: + age_idxs.append(i) + elif stripped == "" or stripped.startswith("#"): + continue + else: break - elif stripped == "" or stripped.startswith("#"): - continue - else: - break # next key, age block ended + return age_idxs, in_target + + age_idxs, found = find_target_age_lines() + if not found: + return False + target_idx = next((i for i in age_idxs if pubkey in lines[i]), None) if target_idx is None: - return True # nothing to remove — already absent + return True # already absent del lines[target_idx] - # Fix a now-dangling trailing comma on the new last age line if any. - # Find the new last age line in this rule's age block. - in_target_rule = False - age_block_start = None - last_age_idx = None - for i, line in enumerate(lines): - stripped = line.strip() - if stripped.startswith("- path_regex:"): - in_target_rule = path_regex_pattern in line - age_block_start = None - continue - if not in_target_rule: - continue - if "age: >-" in line: - age_block_start = i - continue - if age_block_start is None: - continue - if "age1" in stripped: - last_age_idx = i - elif stripped == "" or stripped.startswith("#"): - continue - else: - break - if last_age_idx is not None: + # After deletion, fix trailing comma on the new last age line. + new_age_idxs, _ = find_target_age_lines() + if new_age_idxs: + last_age_idx = new_age_idxs[-1] last_line = lines[last_age_idx] if last_line.rstrip().endswith(","): lines[last_age_idx] = last_line.rstrip().rstrip(",") + "\n"