Auto-rename origin during token sync
This commit is contained in:
@@ -191,15 +191,6 @@ git clone http://77.90.8.171:3001/edu-tools/rv-launcher.git
|
|||||||
cd rv-launcher
|
cd rv-launcher
|
||||||
```
|
```
|
||||||
|
|
||||||
Etap 3: zmień nazwę remota z `origin` na `r1`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git remote rename origin r1
|
|
||||||
```
|
|
||||||
|
|
||||||
`tokens.json` jest mapowany na nazwy git remotes, dlatego repo launchera ma
|
|
||||||
używać remota `r1`.
|
|
||||||
|
|
||||||
Po `git clone` workspace wygląda tak:
|
Po `git clone` workspace wygląda tak:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@@ -210,7 +201,7 @@ Po `git clone` workspace wygląda tak:
|
|||||||
└── tokens.json
|
└── tokens.json
|
||||||
```
|
```
|
||||||
|
|
||||||
Etap 4: sprawdź store i wpisz credentials ze store do remota `r1`:
|
Etap 3: sprawdź store i wpisz credentials ze store do remota `r1`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./rvctl tokens list store
|
./rvctl tokens list store
|
||||||
@@ -220,6 +211,8 @@ Etap 4: sprawdź store i wpisz credentials ze store do remota `r1`:
|
|||||||
`tokens list store` sprawdza, czy skopiowany `tokens.json` zawiera wpis dla
|
`tokens list store` sprawdza, czy skopiowany `tokens.json` zawiera wpis dla
|
||||||
remota `r1`. `tokens sync store r1` bierze token ze store i wpisuje credentials
|
remota `r1`. `tokens sync store r1` bierze token ze store i wpisuje credentials
|
||||||
do git remota `r1`, tak aby kolejne operacje Git mogły używać tego tokena.
|
do git remota `r1`, tak aby kolejne operacje Git mogły używać tego tokena.
|
||||||
|
Jeżeli po `git clone` repo ma tylko remote `origin` wskazujący to samo repo,
|
||||||
|
`rvctl` automatycznie przemianuje go na `r1`.
|
||||||
|
|
||||||
`list store` powinien pokazać token ze store:
|
`list store` powinien pokazać token ze store:
|
||||||
|
|
||||||
@@ -235,6 +228,7 @@ item source kind server proto host org repo use
|
|||||||
```text
|
```text
|
||||||
repo_root /home/user/dev/workspace/rv/tools/rv-launcher
|
repo_root /home/user/dev/workspace/rv/tools/rv-launcher
|
||||||
remote r1
|
remote r1
|
||||||
|
renamed_from origin
|
||||||
server http://77.90.8.171:3001
|
server http://77.90.8.171:3001
|
||||||
user u1
|
user u1
|
||||||
id r1
|
id r1
|
||||||
@@ -242,7 +236,7 @@ status updated
|
|||||||
url http://77.90.8.171:3001/edu-tools/rv-launcher.git
|
url http://77.90.8.171:3001/edu-tools/rv-launcher.git
|
||||||
```
|
```
|
||||||
|
|
||||||
Etap 5: odśwież metadane tokena i porównaj store z remote:
|
Etap 4: odśwież metadane tokena i porównaj store z remote:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./rvctl tokens update r1
|
./rvctl tokens update r1
|
||||||
@@ -263,7 +257,7 @@ item server proto host org repo user remote tok
|
|||||||
1 gitea http 77.90.8.171:3001 edu-tools rv-launcher u1 r1 r1 * e59cc...13be forever
|
1 gitea http 77.90.8.171:3001 edu-tools rv-launcher u1 r1 r1 * e59cc...13be forever
|
||||||
```
|
```
|
||||||
|
|
||||||
Etap 6: po operacjach Git możesz usunąć sekret z `.git/config`, zostawiając
|
Etap 5: po operacjach Git możesz usunąć sekret z `.git/config`, zostawiając
|
||||||
token tylko w store:
|
token tylko w store:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -281,6 +275,29 @@ item server proto host org repo user remote tok
|
|||||||
1 gitea http 77.90.8.171:3001 edu-tools rv-launcher u1 r1 r1 S e59cc...13be forever
|
1 gitea http 77.90.8.171:3001 edu-tools rv-launcher u1 r1 r1 S e59cc...13be forever
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Szybki start
|
||||||
|
|
||||||
|
Najpierw zobacz konfigurację i dostępne komendy:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./rvctl
|
||||||
|
./rvctl show-config
|
||||||
|
```
|
||||||
|
|
||||||
|
Typowy przepływ pracy:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./rvctl tokens compare
|
||||||
|
./rvctl list-series
|
||||||
|
./rvctl list-cards inf
|
||||||
|
./rvctl tmux-container inf 03 --dry-run
|
||||||
|
./rvctl tmux-container inf 03 --session rv-inf03 --attach
|
||||||
|
./rvctl submission inf 03 --class 4i --nick u1
|
||||||
|
```
|
||||||
|
|
||||||
|
`--dry-run` jest przydatny przy sprawdzaniu planu uruchomienia lub konfiguracji
|
||||||
|
repo, zanim narzędzie coś zmieni.
|
||||||
|
|
||||||
### Po pobraniu kart pracy
|
### Po pobraniu kart pracy
|
||||||
|
|
||||||
Karty trafiają do `series` w workspace:
|
Karty trafiają do `series` w workspace:
|
||||||
@@ -320,29 +337,6 @@ Repozytoria źródłowe poza workspace, na przykład `~/dev/edu/repos/rv`, są
|
|||||||
zapleczem dla autora materiałów albo fallbackiem dla narzędzi. Nie są wymagane
|
zapleczem dla autora materiałów albo fallbackiem dla narzędzi. Nie są wymagane
|
||||||
do zwykłej pracy w workspace.
|
do zwykłej pracy w workspace.
|
||||||
|
|
||||||
## Szybki start
|
|
||||||
|
|
||||||
Najpierw zobacz konfigurację i dostępne komendy:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./rvctl
|
|
||||||
./rvctl show-config
|
|
||||||
```
|
|
||||||
|
|
||||||
Typowy przepływ pracy:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./rvctl tokens compare
|
|
||||||
./rvctl list-series
|
|
||||||
./rvctl list-cards inf
|
|
||||||
./rvctl tmux-container inf 03 --dry-run
|
|
||||||
./rvctl tmux-container inf 03 --session rv-inf03 --attach
|
|
||||||
./rvctl submission inf 03 --class 4i --nick u1
|
|
||||||
```
|
|
||||||
|
|
||||||
`--dry-run` jest przydatny przy sprawdzaniu planu uruchomienia lub konfiguracji
|
|
||||||
repo, zanim narzędzie coś zmieni.
|
|
||||||
|
|
||||||
## Dokumentacja
|
## Dokumentacja
|
||||||
|
|
||||||
- `doc/rvctl.md` - techniczna dokumentacja CLI: wszystkie komendy, argumenty
|
- `doc/rvctl.md` - techniczna dokumentacja CLI: wszystkie komendy, argumenty
|
||||||
|
|||||||
@@ -447,6 +447,9 @@ Zapisuje dane auth z rekordu `REMOTE_ID` w `tokens.json` do git remote o tej
|
|||||||
samej nazwie. Jeśli remote jeszcze nie istnieje, URL jest budowany z pól
|
samej nazwie. Jeśli remote jeszcze nie istnieje, URL jest budowany z pól
|
||||||
`server.endpoint`, `org` i `repo` w `tokens.json`.
|
`server.endpoint`, `org` i `repo` w `tokens.json`.
|
||||||
|
|
||||||
|
Jeżeli repo ma tylko remote `origin` wskazujący ten sam URL, `sync store`
|
||||||
|
automatycznie przemianuje `origin` na `REMOTE_ID` przed wpisaniem credentials.
|
||||||
|
|
||||||
Przełączniki:
|
Przełączniki:
|
||||||
|
|
||||||
- `--repo PATH`
|
- `--repo PATH`
|
||||||
|
|||||||
@@ -136,6 +136,9 @@ Jeśli remote `r1` nie istnieje, `rvctl` buduje URL z pól `server.endpoint`,
|
|||||||
http://77.90.8.171:3001/edu-tools/rv-launcher.git
|
http://77.90.8.171:3001/edu-tools/rv-launcher.git
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Jeżeli w repo istnieje tylko `origin` wskazujący ten sam URL, `sync store r1`
|
||||||
|
automatycznie przemianuje `origin` na `r1`, a potem wpisze credentials.
|
||||||
|
|
||||||
Opcjonalnie można podać URL ręcznie:
|
Opcjonalnie można podać URL ręcznie:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -1939,6 +1939,35 @@ def remote_url_from_token_record(token_record: dict) -> str:
|
|||||||
return f"{endpoint}/{quote(owner, safe='')}/{quote(repo_name, safe='')}"
|
return f"{endpoint}/{quote(owner, safe='')}/{quote(repo_name, safe='')}"
|
||||||
|
|
||||||
|
|
||||||
|
def remote_urls_point_to_same_repo(left_url: str, right_url: str) -> bool:
|
||||||
|
try:
|
||||||
|
left_sanitized, _ = sanitize_remote_url(left_url)
|
||||||
|
right_sanitized, _ = sanitize_remote_url(right_url)
|
||||||
|
except SystemExit:
|
||||||
|
return False
|
||||||
|
return left_sanitized.rstrip("/") == right_sanitized.rstrip("/")
|
||||||
|
|
||||||
|
|
||||||
|
def find_origin_rename_candidate(
|
||||||
|
config: WorkspaceConfig,
|
||||||
|
repo_root: Path,
|
||||||
|
target_remote: str,
|
||||||
|
target_url: str,
|
||||||
|
) -> tuple[str, str] | None:
|
||||||
|
origin_remote = config.git.origin_remote
|
||||||
|
if not origin_remote or origin_remote == target_remote:
|
||||||
|
return None
|
||||||
|
if git_capture(repo_root, ["remote", "get-url", target_remote]) is not None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
origin_url = git_capture(repo_root, ["remote", "get-url", origin_remote])
|
||||||
|
if not origin_url:
|
||||||
|
return None
|
||||||
|
if not remote_urls_point_to_same_repo(origin_url, target_url):
|
||||||
|
return None
|
||||||
|
return origin_remote, origin_url
|
||||||
|
|
||||||
|
|
||||||
def resolve_repo_argument(repo_arg: str | None) -> Path:
|
def resolve_repo_argument(repo_arg: str | None) -> Path:
|
||||||
return Path(repo_arg).expanduser().resolve() if repo_arg else Path.cwd().resolve()
|
return Path(repo_arg).expanduser().resolve() if repo_arg else Path.cwd().resolve()
|
||||||
|
|
||||||
@@ -2171,6 +2200,7 @@ def run_tokens_sync(config: WorkspaceConfig, args: argparse.Namespace) -> None:
|
|||||||
args.repo = str(repo_path)
|
args.repo = str(repo_path)
|
||||||
args.remote = args.remote_id
|
args.remote = args.remote_id
|
||||||
args.token_name = args.remote_id
|
args.token_name = args.remote_id
|
||||||
|
args.auto_rename_origin = True
|
||||||
run_tokens_write(config, args)
|
run_tokens_write(config, args)
|
||||||
return
|
return
|
||||||
raise SystemExit(f"Unsupported tokens sync direction: {args.direction}")
|
raise SystemExit(f"Unsupported tokens sync direction: {args.direction}")
|
||||||
@@ -2255,11 +2285,17 @@ def run_tokens_write(config: WorkspaceConfig, args: argparse.Namespace) -> None:
|
|||||||
f"Missing target remote URL and tokens.json has no org/repo for: {server_endpoint}:{remote_id}"
|
f"Missing target remote URL and tokens.json has no org/repo for: {server_endpoint}:{remote_id}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
rename_candidate = None
|
||||||
|
if getattr(args, "auto_rename_origin", False) and existing_remote_url is None:
|
||||||
|
rename_candidate = find_origin_rename_candidate(config, repo_root, args.remote, target_url)
|
||||||
|
if rename_candidate:
|
||||||
|
_, existing_remote_url = rename_candidate
|
||||||
|
|
||||||
final_url = credentialed_remote_url(target_url, user_name, token_value)
|
final_url = credentialed_remote_url(target_url, user_name, token_value)
|
||||||
status = "added" if existing_remote_url is None else "updated"
|
status = "added" if existing_remote_url is None else "updated"
|
||||||
existing_credentials = remote_credentials(existing_remote_url) if existing_remote_url else None
|
existing_credentials = remote_credentials(existing_remote_url) if existing_remote_url else None
|
||||||
if existing_credentials == (user_name, token_value):
|
if existing_credentials == (user_name, token_value):
|
||||||
status = "unchanged"
|
status = "renamed" if rename_candidate else "unchanged"
|
||||||
elif existing_credentials is not None and not args.replace:
|
elif existing_credentials is not None and not args.replace:
|
||||||
raise SystemExit(
|
raise SystemExit(
|
||||||
f"Remote '{args.remote}' already has different credentials. "
|
f"Remote '{args.remote}' already has different credentials. "
|
||||||
@@ -2268,6 +2304,8 @@ def run_tokens_write(config: WorkspaceConfig, args: argparse.Namespace) -> None:
|
|||||||
|
|
||||||
print(f"repo_root\t{repo_root}")
|
print(f"repo_root\t{repo_root}")
|
||||||
print(f"remote\t{args.remote}")
|
print(f"remote\t{args.remote}")
|
||||||
|
if rename_candidate:
|
||||||
|
print(f"renamed_from\t{rename_candidate[0]}")
|
||||||
print(f"server\t{server_endpoint}")
|
print(f"server\t{server_endpoint}")
|
||||||
print(f"user\t{user_name}")
|
print(f"user\t{user_name}")
|
||||||
print(f"id\t{remote_id}")
|
print(f"id\t{remote_id}")
|
||||||
@@ -2277,6 +2315,11 @@ def run_tokens_write(config: WorkspaceConfig, args: argparse.Namespace) -> None:
|
|||||||
if args.dry_run or status == "unchanged":
|
if args.dry_run or status == "unchanged":
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if rename_candidate:
|
||||||
|
subprocess.run(
|
||||||
|
["git", "-C", str(repo_root), "remote", "rename", rename_candidate[0], args.remote],
|
||||||
|
check=True,
|
||||||
|
)
|
||||||
set_git_remote(repo_root, args.remote, final_url)
|
set_git_remote(repo_root, args.remote, final_url)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user