diff --git a/doc/rvctl.md b/doc/rvctl.md index 5f17805..2617a62 100644 --- a/doc/rvctl.md +++ b/doc/rvctl.md @@ -444,14 +444,15 @@ Przyklad: ## `tokens sync store REMOTE_ID` Zapisuje dane auth z rekordu `REMOTE_ID` w `tokens.json` do git remote o tej -samej nazwie. +samej nazwie. Jesli remote jeszcze nie istnieje, URL jest budowany z pol +`server.endpoint`, `org` i `repo` w `tokens.json`. Przelaczniki: - `--repo PATH` Sciezka wewnatrz docelowego repo. Domyslnie biezacy katalog. - `--url URL` - URL remota, jesli remote jeszcze nie istnieje. + Opcjonalny URL remota. Nadpisuje URL zbudowany z `tokens.json`. - `--server ENDPOINT` Endpoint serwera z `tokens.json`. - `--replace` @@ -569,7 +570,7 @@ Przelaczniki: - `--remote NAME` Nazwa remota do aktualizacji lub utworzenia. - `--url URL` - URL remota, jesli remote jeszcze nie istnieje. + Opcjonalny URL remota. Nadpisuje URL zbudowany z `tokens.json`. - `--server ENDPOINT` Endpoint serwera z `tokens.json`. - `--user NAME` diff --git a/doc/tokens.md b/doc/tokens.md index d647634..c1cb18c 100644 --- a/doc/tokens.md +++ b/doc/tokens.md @@ -215,7 +215,7 @@ Jesli token ma zostac tylko w `tokens.json`, usun git remote: Jesli trzeba ponownie utworzyc remote z sekretem ze store: ```bash -./rvctl tokens sync store r1 --url http://77.90.8.171:3001/edu-tools/rv-launcher.git +./rvctl tokens sync store r1 ``` ## Komendy @@ -283,7 +283,9 @@ Nie zmienia git remote URL-a i nie kopiuje sekretu z remote. ### `tokens sync store REMOTE_ID` Zapisuje dane z rekordu `REMOTE_ID` w `tokens.json` do git remote o tej samej -nazwie. Bez `--repo` zapisuje do repo zawierajacego `rvctl`. +nazwie. Jesli remote jeszcze nie istnieje, URL jest budowany z pol +`server.endpoint`, `org` i `repo` w `tokens.json`. Bez `--repo` zapisuje do repo +zawierajacego `rvctl`. ```bash ./rvctl tokens sync store r1 diff --git a/rvctl.py b/rvctl.py index 19a20d8..3b361db 100644 --- a/rvctl.py +++ b/rvctl.py @@ -1891,6 +1891,17 @@ def credentialed_remote_url(remote_url: str, user_name: str, token_value: str) - return urlunsplit((split_url.scheme, netloc, split_url.path, split_url.query, split_url.fragment)) +def remote_url_from_token_record(token_record: dict) -> str: + endpoint = token_server_endpoint(token_record).rstrip("/") + owner = str(token_record.get("org", "")).strip("/") + repo_name = str(token_record.get("repo", "")).strip("/") + if not endpoint or not owner or not repo_name: + return "" + if not repo_name.endswith(".git"): + repo_name = f"{repo_name}.git" + return f"{endpoint}/{quote(owner, safe='')}/{quote(repo_name, safe='')}" + + def resolve_repo_argument(repo_arg: str | None) -> Path: return Path(repo_arg).expanduser().resolve() if repo_arg else Path.cwd().resolve() @@ -2179,16 +2190,16 @@ def run_tokens_write(config: WorkspaceConfig, args: argparse.Namespace) -> None: token_data = load_token_store(config) existing_remote_url = git_capture(repo_root, ["remote", "get-url", args.remote]) target_url = args.url or existing_remote_url - if not target_url: - raise SystemExit("Missing target remote URL. Provide --url or create the remote first.") - - target_server_info = server_info_from_url(config, target_url) - if target_server_info is None: - raise SystemExit(f"Only http/https remote URLs are supported: {target_url}") + target_endpoint = None + if target_url: + target_server_info = server_info_from_url(config, target_url) + if target_server_info is None: + raise SystemExit(f"Only http/https remote URLs are supported: {target_url}") + target_endpoint = target_server_info["endpoint"] token_record = resolve_token_from_store( token_data, - args.server or target_server_info["endpoint"], + args.server or target_endpoint, args.token_name or args.remote, args.user, ) @@ -2200,6 +2211,12 @@ def run_tokens_write(config: WorkspaceConfig, args: argparse.Namespace) -> None: raise SystemExit(f"Token value is empty in tokens.json: {server_endpoint}:{remote_id}") if not user_name: raise SystemExit(f"Token user is empty in tokens.json: {server_endpoint}:{remote_id}") + if not target_url: + target_url = remote_url_from_token_record(token_record) + if not target_url: + raise SystemExit( + f"Missing target remote URL and tokens.json has no org/repo for: {server_endpoint}:{remote_id}" + ) final_url = credentialed_remote_url(target_url, user_name, token_value) status = "added" if existing_remote_url is None else "updated" @@ -2755,7 +2772,7 @@ def build_parser() -> argparse.ArgumentParser: "--repo", help="Path inside a target git repo. Default: repo containing rvctl.", ) - tokens_sync_parser.add_argument("--url", help="Target remote URL used when direction is 'store' and the remote does not exist yet.") + tokens_sync_parser.add_argument("--url", help="Override target remote URL when writing store -> remote.") add_store_selection_options(tokens_sync_parser) tokens_sync_parser.add_argument("--replace", action="store_true", help="Replace different credentials when writing store -> remote.") tokens_sync_parser.add_argument("--dry-run", action="store_true", help="Print the planned sync without writing it.") @@ -2779,7 +2796,7 @@ def build_parser() -> argparse.ArgumentParser: ) add_repo_option(tokens_write_parser) tokens_write_parser.add_argument("--remote", help="Remote name to update or create.") - tokens_write_parser.add_argument("--url", help="Target remote URL if the remote does not exist yet.") + tokens_write_parser.add_argument("--url", help="Override target remote URL when creating or updating the remote.") add_store_selection_options(tokens_write_parser) tokens_write_parser.add_argument("--replace", action="store_true", help="Replace different credentials in the remote URL.") tokens_write_parser.add_argument("--dry-run", action="store_true", help="Print the planned update without writing it.") @@ -2797,7 +2814,7 @@ def build_parser() -> argparse.ArgumentParser: ) add_repo_option(tokens_update_parser) tokens_update_parser.add_argument("--remote", help="Remote name used when --from store.") - tokens_update_parser.add_argument("--url", help="Target remote URL used when --from store.") + tokens_update_parser.add_argument("--url", help="Override target remote URL when --from store.") add_store_selection_options(tokens_update_parser) tokens_update_parser.add_argument("--replace", action="store_true", help="Replace different credentials when writing to remotes.") tokens_update_parser.add_argument("--dry-run", action="store_true", help="Print the planned update without writing it.")