Auto sync workspace manifest on first use

This commit is contained in:
mpabi
2026-04-29 20:47:21 +02:00
parent 170d8435aa
commit f959708363
5 changed files with 59 additions and 17 deletions
+7 -5
View File
@@ -296,10 +296,13 @@ Po konfiguracji tokenów najpierw sprawdź stan store:
./rvctl tokens compare ./rvctl tokens compare
``` ```
Następnie pobierz albo zaktualizuj publiczny manifest wspólnego workspace: Następnie wylistuj dostępne serie. Jeżeli manifestu `workspace-info` jeszcze
nie ma, `rvctl` pobierze go automatycznie do `meta/workspace-info`. Jeżeli
katalog `series` w workspace jeszcze nie istnieje, `rvctl` utworzy go
automatycznie:
```bash ```bash
./rvctl workspace sync ./rvctl series list
``` ```
Manifest trafia do: Manifest trafia do:
@@ -308,11 +311,10 @@ Manifest trafia do:
~/dev/workspace/rv/meta/workspace-info ~/dev/workspace/rv/meta/workspace-info
``` ```
Następnie wylistuj dostępne serie. Jeżeli katalog `series` w workspace jeszcze Jeżeli chcesz jawnie odświeżyć istniejący manifest, użyj:
nie istnieje, `rvctl` utworzy go automatycznie:
```bash ```bash
./rvctl series list ./rvctl workspace sync
``` ```
Przykładowy wynik: Przykładowy wynik:
+6 -1
View File
@@ -285,9 +285,14 @@ Klonuje albo aktualizuje repo `edu-workspace/workspace-info` do katalogu
./rvctl workspace sync --dry-run ./rvctl workspace sync --dry-run
``` ```
Jeżeli lokalnej kopii manifestu jeszcze nie ma, komendy zależne od manifestu
same wykonują bootstrap przez `git clone`. Istniejącego manifestu nie
aktualizują automatycznie; do tego służy jawne `workspace sync`.
## `series list` ## `series list`
Listuje serie dostępne w `workspace-info` i workspace. Komenda tworzy Listuje serie dostępne w `workspace-info` i workspace. Jeżeli `workspace-info`
jeszcze nie istnieje lokalnie, komenda pobiera je automatycznie. Komenda tworzy
`series_root`, jeżeli katalog jeszcze nie istnieje. `series_root`, jeżeli katalog jeszcze nie istnieje.
Format wyjścia: Format wyjścia:
+6 -4
View File
@@ -14,13 +14,14 @@ Komendy kart pracy dzielimy na trzy poziomy:
`rvctl` tworzy `series_root`, jeżeli katalog jeszcze nie istnieje. Lista serii `rvctl` tworzy `series_root`, jeżeli katalog jeszcze nie istnieje. Lista serii
i kart pochodzi docelowo z publicznego manifestu i kart pochodzi docelowo z publicznego manifestu
`~/dev/workspace/rv/meta/workspace-info/workspace.json`. Jeżeli manifestu nie `~/dev/workspace/rv/meta/workspace-info/workspace.json`. Jeżeli manifestu nie
ma, narzędzie używa starego fallbacku przez `original_series_root`. ma, komendy zależne od serii automatycznie klonują repo
`edu-workspace/workspace-info`. Jeżeli klonowanie nie jest możliwe, narzędzie
używa starego fallbacku przez `original_series_root`.
## Szybki przepływ ## Szybki przepływ
```bash ```bash
./rvctl tokens compare ./rvctl tokens compare
./rvctl workspace sync
./rvctl series list ./rvctl series list
./rvctl series cards list inf ./rvctl series cards list inf
./rvctl series cards fetch inf bss ./rvctl series cards fetch inf bss
@@ -35,8 +36,9 @@ Dla karty `bss` właściwym repo jest `lab-rv32i-strlen-bss-data-stack`.
### `series list` ### `series list`
Listuje dostępne serie z manifestu `workspace-info` oraz liczbę kart już Listuje dostępne serie z manifestu `workspace-info` oraz liczbę kart już
pobranych do lokalnego workspace. Jeżeli `~/dev/workspace/rv/series` nie pobranych do lokalnego workspace. Jeżeli manifestu jeszcze nie ma, komenda
istnieje, komenda tworzy ten katalog. pobiera go automatycznie. Jeżeli `~/dev/workspace/rv/series` nie istnieje,
komenda tworzy ten katalog.
```bash ```bash
./rvctl series list ./rvctl series list
+5
View File
@@ -46,3 +46,8 @@ Aktualizacja manifestu:
```bash ```bash
./rvctl workspace sync ./rvctl workspace sync
``` ```
Komendy zależne od manifestu, na przykład `series list`, `series cards list`,
`series cards fetch` i `tasks list`, automatycznie klonują `workspace-info`,
jeżeli lokalnej kopii jeszcze nie ma. Nie wykonują automatycznego `pull` na
istniejącym repo; do odświeżania służy jawne `workspace sync`.
+35 -7
View File
@@ -3325,6 +3325,38 @@ def workspace_info_status(config: WorkspaceConfig) -> str:
return "missing" return "missing"
def sync_workspace_info(config: WorkspaceConfig, pull_existing: bool = True) -> str:
info_root = workspace_info_root(config)
info_root.parent.mkdir(parents=True, exist_ok=True)
if (info_root / ".git").is_dir():
if pull_existing:
subprocess.run(["git", "-C", str(info_root), "pull", "--ff-only"], check=True)
config.workspace_info = json.loads(config.workspace_info_path.read_text(encoding="utf-8"))
return "pulled"
if config.workspace_info_path.is_file():
config.workspace_info = json.loads(config.workspace_info_path.read_text(encoding="utf-8"))
return "existing"
raise SystemExit(f"Workspace info repo exists but manifest is missing: {config.workspace_info_path}")
if info_root.exists():
raise SystemExit(f"Workspace info path exists but is not a git repo: {info_root}")
print(f"workspace-info missing; cloning {config.workspace_info_url}", file=sys.stderr)
subprocess.run(["git", "clone", config.workspace_info_url, str(info_root)], check=True)
if not config.workspace_info_path.is_file():
raise SystemExit(f"Workspace info clone does not contain manifest: {config.workspace_info_path}")
config.workspace_info = json.loads(config.workspace_info_path.read_text(encoding="utf-8"))
return "cloned"
def ensure_workspace_info(config: WorkspaceConfig) -> None:
if config.workspace_info:
return
if config.workspace_info_path.is_file():
config.workspace_info = json.loads(config.workspace_info_path.read_text(encoding="utf-8"))
return
sync_workspace_info(config, pull_existing=False)
def run_workspace(config: WorkspaceConfig, args: argparse.Namespace) -> None: def run_workspace(config: WorkspaceConfig, args: argparse.Namespace) -> None:
if args.workspace_command == "show": if args.workspace_command == "show":
print(f"workspace_info_path\t{config.workspace_info_path}") print(f"workspace_info_path\t{config.workspace_info_path}")
@@ -3343,13 +3375,7 @@ def run_workspace(config: WorkspaceConfig, args: argparse.Namespace) -> None:
print(f"status\t{workspace_info_status(config)}") print(f"status\t{workspace_info_status(config)}")
print(f"command\t{'pull' if (info_root / '.git').is_dir() else 'clone'}") print(f"command\t{'pull' if (info_root / '.git').is_dir() else 'clone'}")
return return
info_root.parent.mkdir(parents=True, exist_ok=True) sync_workspace_info(config, pull_existing=True)
if (info_root / ".git").is_dir():
subprocess.run(["git", "-C", str(info_root), "pull", "--ff-only"], check=True)
elif info_root.exists():
raise SystemExit(f"Workspace info path exists but is not a git repo: {info_root}")
else:
subprocess.run(["git", "clone", config.workspace_info_url, str(info_root)], check=True)
print(f"workspace_info_path\t{config.workspace_info_path}") print(f"workspace_info_path\t{config.workspace_info_path}")
print(f"status\tready") print(f"status\tready")
return return
@@ -3810,6 +3836,8 @@ def main() -> int:
parser = build_parser() parser = build_parser()
args = parser.parse_args() args = parser.parse_args()
config = load_config(args.config) config = load_config(args.config)
if args.command in {"list-series", "list-cards", "series", "tasks", "tmux-container", "submission"}:
ensure_workspace_info(config)
if args.command == "show-config": if args.command == "show-config":
print_config(config) print_config(config)