From 840f8badf9695ca13d239641adb86a93cf8e78bc Mon Sep 17 00:00:00 2001 From: mpabi Date: Sun, 26 Apr 2026 20:05:18 +0200 Subject: [PATCH] Decompose token endpoints in scan output --- README.md | 5 ++- doc/rvctl.md | 21 ++++++----- doc/tokens.md | 10 +++-- rvctl.py | 101 ++++++++++++++++++++++++++++++++++++-------------- 4 files changed, 94 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index c2da513..cf8a39f 100644 --- a/README.md +++ b/README.md @@ -159,9 +159,10 @@ Podstawowe komendy tokenow: `tokens scan` wypisuje waska tabele. Dla jednego endpointu zobaczysz osobny wiersz `source=repo` oraz osobny wiersz `source=tokens.json`. Ten sam numer `item` laczy oba wiersze w pare dla jednego endpointu. -Kolumny `has_token` i `sync` pokazuja, gdzie jest token i czy repo zgadza sie +Kolumny `token` i `sync` pokazuja, gdzie jest token i czy repo zgadza sie z `tokens.json`. Kolumna `id` pokazuje `r1` dla tokena w repo albo `t1` dla -tokena w `tokens.json`, bez pokazywania sekretu. +tokenu w `tokens.json`, bez pokazywania sekretu. Endpoint jest rozbity na +`server`, `scheme`, `host` i `port`. ## Fetch i switch diff --git a/doc/rvctl.md b/doc/rvctl.md index 3bc73bd..47648ad 100644 --- a/doc/rvctl.md +++ b/doc/rvctl.md @@ -305,22 +305,23 @@ Typowy wynik: ```text items -item source id credential user has_token sync endpoint ----- ----------- ---------- ---------- ---------- --------- ----- -------------------------------- -1 repo r1 auth u1 yes yes http://77.90.8.171:3001 -1 tokens.json t1 store u1 yes yes http://77.90.8.171:3001 +item source id server scheme host port credential repo_user store_user token sync +---- ----------- ---------- ------ ------ --------------- ----- ---------- --------- ---------- ----- ---- +1 repo r1 gitea http 77.90.8.171 3001 auth u1 u1 yes yes +1 tokens.json t1 gitea http 77.90.8.171 3001 store u1 u1 yes yes ``` Jesli remote istnieje, ale ma URL bez `LOGIN:TOKEN@`, wynik bedzie mial -w wierszu `repo` wartosci `credential=plain` i `has_token=no`. Jezeli ten sam +w wierszu `repo` wartosci `credential=plain` i `token=no`. Jezeli ten sam endpoint istnieje w `tokens.json`, drugi wiersz tego samego `item` pokaze -`source=tokens.json`, `id=t1` i `has_token=yes`. +`source=tokens.json`, `id=t1`, `store_user=u1` i `token=yes`. Ten sam numer `item` oznacza jedna pare logiczna dla jednego endpointu. Wiersz `source=repo` pokazuje stan remote, a wiersz `source=tokens.json` pokazuje stan lokalnego store. Kolumna `sync` jest flaga zgodnosci calej pary repo/store. Kolumna `id` pokazuje identyfikator miejsca przechowywania tokena: dla repo jest to nazwa remota, na przyklad `r1`, a dla store nazwa tokenu, na przyklad `t1`. +Endpoint jest rozbity na `server`, `scheme`, `host` i `port`. Przyklad: @@ -384,10 +385,10 @@ repo_root... token_path... items -item source id credential user has_token sync endpoint ----- ----------- ---------- ---------- ---------- --------- ----- -------------------------------- -1 repo r1 plain no no http://77.90.8.171:3001 -1 tokens.json t1 store u1 yes no http://77.90.8.171:3001 +item source id server scheme host port credential repo_user store_user token sync +---- ----------- ---------- ------ ------ --------------- ----- ---------- --------- ---------- ----- ---- +1 repo r1 gitea http 77.90.8.171 3001 plain u1 no no +1 tokens.json t1 gitea http 77.90.8.171 3001 store u1 u1 yes no status itemvalue diff --git a/doc/tokens.md b/doc/tokens.md index aced407..96e0136 100644 --- a/doc/tokens.md +++ b/doc/tokens.md @@ -105,11 +105,15 @@ Kolumny w tabeli `items`: - `item` - numer porownywanego endpointu - `source` - `repo` albo `tokens.json` - `id` - identyfikator miejsca tokena: remote `r1` dla repo albo token `t1` dla `tokens.json` +- `server` - typ serwera, na przyklad `gitea` +- `scheme` - schemat URL, na przyklad `http` +- `host` - host endpointu, na przyklad `77.90.8.171` +- `port` - port endpointu, na przyklad `3001` - `credential` - typ wpisu: `auth`, `plain`, `store` albo `missing` -- `user` - login odczytany z URL albo ze store -- `has_token` - `yes` albo `no`, czyli czy dane zrodlo ma token dla endpointu +- `repo_user` - login odczytany z remote URL-i repo +- `store_user` - login odczytany z `tokens.json` +- `token` - `yes` albo `no`, czyli czy dane zrodlo ma token dla endpointu - `sync` - `yes` albo `no`, czyli czy para repo/store jest zgodna -- `endpoint` - endpoint serwera bez sekretu, trzymany jako ostatnia kolumna i przycinany do szerokosci tabeli Tabela nie wypisuje sekretu tokena. Jezeli token jest w remote, `id` pokazuje nazwe remota, na przyklad `r1`. Jezeli token jest w `tokens.json`, `id` diff --git a/rvctl.py b/rvctl.py index ff3c5a3..50ae9ed 100644 --- a/rvctl.py +++ b/rvctl.py @@ -671,11 +671,15 @@ TOKEN_ITEM_COLUMNS = [ ("item", 4), ("source", 11), ("id", 10), + ("server", 6), + ("scheme", 6), + ("host", 15), + ("port", 5), ("credential", 10), - ("user", 10), - ("has_token", 9), - ("sync", 5), - ("endpoint", 32), + ("repo_user", 9), + ("store_user", 10), + ("token", 5), + ("sync", 4), ] @@ -699,6 +703,36 @@ def sync_flag(status_name: str) -> str: return "yes" if status_name == "in_sync" else "no" +def users_label(server_entry: dict | None) -> str: + if server_entry is None: + return "" + return ",".join(sorted(str(user_name) for user_name in server_entry.get("users", {}))) + + +def endpoint_column_values(endpoint: str, repo_entry: dict | None, store_entry: dict | None) -> dict[str, str]: + values = { + "server": "", + "scheme": "", + "host": "", + "port": "", + } + for server_entry in [repo_entry, store_entry]: + if server_entry is None: + continue + values["server"] = values["server"] or str(server_entry.get("type", "")) + values["scheme"] = values["scheme"] or str(server_entry.get("scheme", "")) + values["host"] = values["host"] or str(server_entry.get("host", "")) + port_value = server_entry.get("port", "") + values["port"] = values["port"] or ("" if port_value is None else str(port_value)) + + split_endpoint = urlsplit(endpoint) + values["scheme"] = values["scheme"] or split_endpoint.scheme + values["host"] = values["host"] or (split_endpoint.hostname or "") + if not values["port"] and split_endpoint.port is not None: + values["port"] = str(split_endpoint.port) + return values + + def print_token_item_rows( endpoint_names: list[str], repo_servers: dict[str, dict], @@ -721,6 +755,10 @@ def print_token_item_rows( status_name, _, _ = compare_server_entries(repo_entry, store_entry) if status_name in status_counts: status_counts[status_name] += 1 + endpoint_values = endpoint_column_values(endpoint, repo_entry, store_entry) + repo_users_label = users_label(repo_entry) + store_users_label = users_label(store_entry) + sync_value = sync_flag(status_name) repo_rows = scan_rows_by_endpoint.get(endpoint, []) if repo_rows: @@ -731,11 +769,12 @@ def print_token_item_rows( "item": item_id, "source": "repo", "id": row["remote"], + **endpoint_values, "credential": row["url_kind"], - "user": row["user"], - "has_token": "yes" if token_label else "no", - "sync": sync_flag(status_name), - "endpoint": endpoint, + "repo_user": row["user"], + "store_user": store_users_label, + "token": "yes" if token_label else "no", + "sync": sync_value, } ) elif repo_entry is None: @@ -743,10 +782,11 @@ def print_token_item_rows( { "item": item_id, "source": "repo", + **endpoint_values, "credential": "missing", - "has_token": "no", - "sync": sync_flag(status_name), - "endpoint": endpoint, + "store_user": store_users_label, + "token": "no", + "sync": sync_value, } ) else: @@ -761,11 +801,12 @@ def print_token_item_rows( "item": item_id, "source": "repo", "id": remote_names, + **endpoint_values, "credential": repo_kind, - "user": user_name, - "has_token": "yes" if token_label else "no", - "sync": sync_flag(status_name), - "endpoint": endpoint, + "repo_user": user_name, + "store_user": store_users_label, + "token": "yes" if token_label else "no", + "sync": sync_value, } ) else: @@ -774,10 +815,11 @@ def print_token_item_rows( "item": item_id, "source": "repo", "id": remote_names, + **endpoint_values, "credential": repo_kind, - "has_token": "yes" if repo_result == "present" else "no", - "sync": sync_flag(status_name), - "endpoint": endpoint, + "store_user": store_users_label, + "token": "yes" if repo_result == "present" else "no", + "sync": sync_value, } ) @@ -786,10 +828,11 @@ def print_token_item_rows( { "item": item_id, "source": "tokens.json", + **endpoint_values, "credential": "missing", - "has_token": "no", - "sync": sync_flag(status_name), - "endpoint": endpoint, + "repo_user": repo_users_label, + "token": "no", + "sync": sync_value, } ) continue @@ -800,10 +843,11 @@ def print_token_item_rows( { "item": item_id, "source": "tokens.json", + **endpoint_values, "credential": "store", - "has_token": "no", - "sync": sync_flag(status_name), - "endpoint": endpoint, + "repo_user": repo_users_label, + "token": "no", + "sync": sync_value, } ) continue @@ -814,11 +858,12 @@ def print_token_item_rows( "item": item_id, "source": "tokens.json", "credential": "store", - "user": user_name, "id": token_name, - "has_token": "yes" if token_name else "no", - "sync": sync_flag(status_name), - "endpoint": endpoint, + **endpoint_values, + "repo_user": repo_users_label, + "store_user": user_name, + "token": "yes" if token_name else "no", + "sync": sync_value, } )