""" Step 1: Scan a restored FCCS backup directory for drawer IDs. Every subdirectory in the backup root corresponds to a drawer. Writes the sorted list of drawer IDs to the configured drawer_id_file. """ import os import sys from fccs_config import ( parse_args, load_config, make_logger, load_lines, check_for_clashes, ) _IGNORE_HEADER = [ "# Drawer IDs to SKIP during export (one ID per line).", "# Lines starting with # are comments and are ignored.", "#", "# Add password-protected or otherwise-excluded drawers here.", "#", "# The IDs auto-added below are prefix clashes: searching them in FCCS", "# pops a selection box that breaks the automation, so they're skipped by", "# default. DELETE or comment out any you actually DO want exported (then", "# handle them manually), and keep the rest.", "", ] def update_ignore_file(ignore_file, clashes, log): """Create ignore.txt if missing and seed it with clash prefix IDs. Never overwrites existing entries — only appends clash prefixes that aren't already present. The shorter (prefix) ID of each clash is the one that triggers the FCCS selection box, so it's the candidate to skip. Returns the list of IDs that were added. """ existing = set(load_lines(ignore_file)) file_exists = os.path.exists(ignore_file) to_add = [(short, matches) for short, matches in clashes if short not in existing] # Existing file already covers every clash — leave it untouched. if file_exists and not to_add: return [] lines = [] if not file_exists: lines.extend(_IGNORE_HEADER) for short, matches in to_add: lines.append(f"# clashes with: {', '.join(matches)}") lines.append(short) mode = "a" if file_exists else "w" with open(ignore_file, mode, encoding="utf-8") as f: if file_exists: f.write("\n") # separate the new block from prior content f.write("\n".join(lines) + "\n") added = [short for short, _ in to_add] if not file_exists: log(f"Created ignore file: {ignore_file}") if added: log(f"Added {len(added)} clash prefix ID(s) to ignore list: " f"{', '.join(added)}") return added def main(): args = parse_args() cfg = load_config(args.config) log = make_logger(cfg.get("paths", "log_file")) backup_dir = cfg.get("paths", "backup_dir") output_file = cfg.get("paths", "drawer_id_file") ignore_file = cfg.get("paths", "ignore_file") if not os.path.isdir(backup_dir): log(f"ERROR: backup directory not found: {backup_dir}") sys.exit(1) drawer_ids = sorted( name for name in os.listdir(backup_dir) if os.path.isdir(os.path.join(backup_dir, name)) ) with open(output_file, "w", encoding="utf-8") as f: for did in drawer_ids: f.write(did + "\n") log(f"Found {len(drawer_ids)} drawers, written to {output_file}") # Flag prefix clashes: FCCS search on the shorter ID pops a selection box. clashes = check_for_clashes(drawer_ids) if clashes: log("-" * 60) log(f"WARNING: {len(clashes)} potential drawer ID clash(es) found.") log("Searching the shorter ID in FCCS may show a selection box " "instead of navigating directly, which breaks the export.") for short, matches in clashes: log(f" {short} -> also matches: {', '.join(matches)}") # Seed ignore.txt with the clash prefixes for review (never overwrites). update_ignore_file(ignore_file, clashes, log) log(f"Review the ignore list: {ignore_file}") log("-" * 60) else: log("No drawer ID prefix clashes found.") # Report which drawers will be skipped by the export. ignored = set(load_lines(ignore_file)) if ignored: present = sorted(ignored & set(drawer_ids)) log(f"Ignore list ({ignore_file}): {len(ignored)} IDs listed, " f"{len(present)} present in this backup — these will be SKIPPED " f"by fccs_export.py: {', '.join(present) if present else '(none present)'}") if __name__ == "__main__": main()