diff --git a/truenas_migrate.py b/truenas_migrate.py index d975102..dd08ef3 100644 --- a/truenas_migrate.py +++ b/truenas_migrate.py @@ -1185,6 +1185,57 @@ def _confirm(label: str) -> bool: return False +def _select_shares(shares: list[dict], share_type: str) -> list[dict]: + """ + Display a numbered list of *shares* and return only those the user selects. + Enter (or 'all') returns all shares unchanged. 'n' / 'none' returns []. + """ + if not shares: + return shares + + print(f"\n {_bold(f'{share_type} shares in archive ({len(shares)}):')} \n") + for i, share in enumerate(shares, 1): + if share_type == "SMB": + name = share.get("name", "") + path = share.get("path", "") + print(f" {_cyan(str(i) + '.')} {name:<22} {_dim(path)}") + else: # NFS + pl = share.get("paths") or [] + path = share.get("path") or (pl[0] if pl else "") + extra = f" {_dim('+ ' + str(len(pl) - 1) + ' more')}" if len(pl) > 1 else "" + print(f" {_cyan(str(i) + '.')} {path}{extra}") + + print() + raw = _prompt( + f" Select {share_type} shares to migrate " + "(e.g. '1 3', Enter = all, 'n' = none)", + default="all", + ) + + low = raw.strip().lower() + if low in ("", "all"): + print(f" {_green('✓')} All {len(shares)} {share_type} share(s) selected.") + return shares + if low in ("n", "none", "0"): + print(f" {_yellow('–')} No {share_type} shares selected.") + return [] + + seen: set[int] = set() + selected: list[dict] = [] + for tok in raw.split(): + if tok.isdigit(): + idx = int(tok) - 1 + if 0 <= idx < len(shares) and idx not in seen: + seen.add(idx) + selected.append(shares[idx]) + + if selected: + print(f" {_green('✓')} {len(selected)} of {len(shares)} {share_type} share(s) selected.") + else: + print(f" {_yellow('–')} No valid selections; skipping {share_type} shares.") + return selected + + def interactive_mode() -> None: """Interactive wizard: pick archive → configure → dry run → confirm → apply.""" print( @@ -1258,6 +1309,13 @@ def interactive_mode() -> None: print() archive_data = parse_archive(str(chosen)) + # 5b ── Select individual shares ─────────────────────────────────────────── + if "smb" in migrate and archive_data["smb_shares"]: + archive_data["smb_shares"] = _select_shares(archive_data["smb_shares"], "SMB") + if "nfs" in migrate and archive_data["nfs_shares"]: + archive_data["nfs_shares"] = _select_shares(archive_data["nfs_shares"], "NFS") + print() + base_ns = dict( debug_tar=str(chosen), dest=host,