RV Launcher
Launcher do workspace rv.
workspace.jsontrzyma sciezki repo oryginalnych, workspace i toolsrvctl.pyzawiera implementacje CLIrvctllistuje serie i karty- szczegolowy opis CLI jest w
doc/rvctl.md - model tokenow i synchronizacji repo <-> store jest w
doc/tokens.md
Model katalogow
Repo oryginalne trzymamy poza workspace:
~/dev/edu/repos/rv
Workspace sluzy do klonow roboczych i cwiczen:
~/dev/workspace/rv
Typowy uklad:
~/dev/edu/repos/rv/rv-launcher
~/dev/edu/repos/rv/rv32i-hazard3-env
~/dev/edu/repos/rv/series/<seria>/<karta>
~/dev/workspace/rv/tools/rv-launcher
~/dev/workspace/rv/tools/rv32i-hazard3-env
~/dev/workspace/rv/series/<seria>/<karta>
Launcher szuka rv32i-hazard3-env najpierw w workspace, a jesli nie znajdzie
klona roboczego, moze uzyc repo oryginalnego z ~/dev/edu/repos/rv.
Karty pracy tez sa rozdzielone:
~/dev/edu/repos/rv/series/...to checkouty zrodlowe, nad ktorymi pracujemy~/dev/workspace/rv/series/...to klony testowe pobierane z Gitea
Launcher wykonuje list-series, list-cards, submission i tmux-container
na kartach z workspace, nie na repo zrodlowych.
Przygotowanie katalogu
Repo treningowe launchera trzymaj pod:
~/dev/workspace/rv/tools/rv-launcher
Bootstrap bez git clone:
mkdir -p ~/dev/workspace/rv/tools
mkdir -p ~/dev/workspace/rv/tools/rv-launcher
cd ~/dev/workspace/rv/tools/rv-launcher
git init
Glowne pliki CLI:
./rvctl
rvctl.py
rvctl jest jedynym publicznym entrypointem. rvctl.py jest implementacja
uruchamiana przez wrapper i nie wymaga osobnego wywolywania przez ucznia.
Uruchomienie bez argumentow pokazuje tabelaryczny skrot komend:
./rvctl
./rvctl tokens
Autoryzacja
Masz dwie drogi.
Droga 1: remote r1 z tokenem w URL
To jest wariant dydaktyczny, jesli uczen ma cwiczyc reczne dodawanie remota z
tokenem do konkretnego zdalnego endpointu. Jesli launcher zobaczy URL w formacie
http://LOGIN:TOKEN@..., mozesz zapisac ten token lokalnie komenda
tokens sync remote r1.
Przyklad:
git remote add r1 http://u1:TOKEN@77.90.8.171:3001/edu-tools/rv-launcher.git
git fetch r1 main
git switch --track -c main r1/main
Droga 2: lokalny tokens/tokens.json
To jest wariant alternatywny, wygodniejszy wtedy, gdy launcher ma sam wykonywac
clone, fetch i push, albo gdy uzytkownik po zajeciach chce pracowac juz na
wlasnych repo bez wpisywania tokena do kazdego remota.
Przed operacjami wymagajacymi autoryzacji dodaj lokalny token do:
~/dev/workspace/rv/tokens/tokens.json
Minimalny format:
{
"version": 3,
"tokens": [
{
"id": "r1",
"value": "TU_WSTAW_TOKEN",
"server": {
"type": "gitea",
"endpoint": "http://77.90.8.171:3001",
"scheme": "http",
"host": "77.90.8.171",
"port": 3001
},
"user": "u1",
"org": "edu-tools",
"repo": "rv-launcher"
}
]
}
Pelny schemat pliku jest w doc/tokens.schema.json.
Plik powinien byc lokalny, niewersjonowany i miec prawa 600.
Przyklad:
mkdir -p ~/dev/workspace/rv/tokens
chmod 700 ~/dev/workspace/rv/tokens
chmod 600 ~/dev/workspace/rv/tokens/tokens.json
Jesli token jest trzymany tylko w tokens/tokens.json, remote r1 moze
byc zapisany bez sekretu:
git remote add r1 http://77.90.8.171:3001/edu-tools/rv-launcher.git
Podstawowe komendy tokenow:
./rvctl tokens scan
./rvctl tokens sync remote r1
./rvctl tokens update r1
./rvctl tokens sync store r1
./rvctl tokens add r1
./rvctl tokens read
./rvctl tokens stats --repo ~/dev/workspace/rv/series/inf/03
tokens scan wypisuje tabele tokens i niczego nie zapisuje: jeden wiersz na
logiczny remote tokena.
token_ref laczy nazwe tokena z markerem po prawej stronie: * oznacza, ze
remote i tokens.json sa zgodne, R oznacza token tylko w remote, a S
token tylko w tokens.json. Kolumny scope, org i repo sa maskami
uprawnien; bez zgodnego wpisu maja wartosc ?????????, ????? albo ????.
Zapis z remote do tokens.json robi tokens sync remote r1.
Odczyt valid i uprawnien z API robi tokens update r1.
Zapis z tokens.json do remota robi tokens sync store r1.
Kolumna valid oznacza, czy token zostal zaakceptowany przez API teraz.
Jesli przy tokenie w tokens.json zapiszesz expires_at, valid moze pokazac
date wygasniecia; bez daty poprawny token pokazuje forever.
Fetch i switch
Domyslna galaz launchera to main.
Wariant preferowany przez r1:
git fetch r1 main
git switch --track -c main r1/main
git pull --ff-only r1 main
Jesli repo bylo sklonowane klasycznie i pracujesz przez origin, odpowiednikiem
jest:
git fetch origin main
git switch main
git pull --ff-only origin main
Jesli chcesz wejsc na inna galaz, na przyklad feat/x, uzyj:
git fetch r1 feat/x
git switch --track -c feat/x r1/feat/x
Wariant przez origin:
git fetch origin feat/x
git switch --track -c feat/x origin/feat/x
Repo odpowiedzi kart pracy
Model pracy kart jest taki:
r1wskazuje repo z materialem zedu-infa1wskazuje wspolne repo odpowiedzi wzsl-inf- kazdy uczen wysyla swoja prace na branch o nazwie swojego nicku
Repo odpowiedzi nie zawiera nicku w nazwie. Launcher buduje je w formacie:
zsl-inf/<repo_z_edu-inf>-<klasa>-<data>
Przyklad:
zsl-inf/lab-rv32i-strlen-bss-data-stack-4i-2026-04-26
Przyklad planu dla ucznia u1:
./rvctl submission inf 03 --class 4i --nick u1
Przyklad konfiguracji remote'ow w repo karty:
./rvctl submission inf 03 --class 4i --nick u1 --apply
Launcher wtedy:
- czyta URL zrodlowego repo z
originaktualnej karty i ustawia go jakor1 - bierze basename tego repo z
edu-infi z niego buduje nazwe repo odpowiedzi - wylicza repo odpowiedzi w
zsl-infi ustawia je jakoa1 - proponuje branch ucznia, na przyklad
u1
Typowy wynik to:
source_repo edu-inf/lab-rv32i-strlen-bss-data-stack
source_remote r1
answer_remote a1
answer_repo zsl-inf/lab-rv32i-strlen-bss-data-stack-4i-2026-04-26
student_branch u1
Wariant alternatywny: git clone
Jesli celem nie jest cwiczenie remote add i fetch, repo treningowe mozna
tez sklonowac klasycznie:
mkdir -p ~/dev/workspace/rv/tools
cd ~/dev/workspace/rv/tools
git clone http://77.90.8.171:3001/edu-tools/rv-launcher.git
cd rv-launcher
Podstawowe komendy
Przyklady:
./rvctl
./rvctl show-config
./rvctl list-series
./rvctl list-cards inf
./rvctl tokens
./rvctl submission inf 03 --class 4i --nick u1
./rvctl tmux-container inf 03 --dry-run
./rvctl tmux-container inf 03 --session rv-inf03 --attach
Skrypt nie trzyma listy kart w JSON-ie. Czyta series/*/* z series_root.