progress: barra di avanzamento per download ed estrazione
Aggiunge src/progress.{c,h}: barra a una riga attiva solo quando stdout e' un
terminale (con output rediretto/pipeline non stampa nulla, quindi l'output resta
identico al client Python: parita' 30/30 invariata).
- due fasi: "Scaricamento" (byte da Content-Length) ed "Estrazione" (byte
compressi consumati + membri processati: nuovo contatore in gz_reader e
callback tar_progress_fn/tar_extract_cb)
- controllo con CELLAR_PROGRESS=auto|bar|plain|off (default auto)
- nessun codice ANSI, solo '\r' e riempimento con spazi; glifi ASCII se la
locale non e' UTF-8, larghezza da TIOCGWINSZ e misurata in colonne (i glifi
UTF-8 sono multi-byte), ridisegno throttled, velocita' a media mobile, ETA
- percorsi d'errore: progress_abort() chiude la riga senza riepilogo; il file
parziale resta come nel client Python
- tests/progress_test.sh: pipe silenziosa, PTY via script (barra, ETA, riepilogo,
nessun ANSI, righe entro la larghezza), modalita' plain e off, integrita' del
file scaricato e della bottiglia installata (13/13 verdi)
- tests/parity_test.sh resta 30/30; mock_server.py con --throttle per i test
This commit is contained in:
@@ -81,6 +81,37 @@ cellar-cli --server http://10.8.0.3:8080 list # override del server
|
||||
|
||||
Exit code: `0` ok, `1` errore HTTP/rete/file, `2` argomenti non validi (come argparse).
|
||||
|
||||
## Barra di avanzamento
|
||||
|
||||
Durante `install`, `wizard-install` e `download` viene mostrata una barra su una riga,
|
||||
con due fasi (`Scaricamento` ed `Estrazione`):
|
||||
|
||||
```
|
||||
Scaricamento [████████████░░░░░░░░░░░░] 58% 6.7 MB/11.5 MB 3.0 MB/s ETA 00:01
|
||||
Estrazione [████████████████████████] 100% 11.5 MB/11.5 MB 178 MB/s membri: 20
|
||||
```
|
||||
|
||||
- **attiva solo se stdout è un terminale**: con output rediretto, in pipeline, in cron o
|
||||
nei log **non stampa nulla** — per questo l'output resta identico al client Python;
|
||||
- controllo con la variabile d'ambiente **`CELLAR_PROGRESS`**:
|
||||
- `auto` (default) → barra su terminale, silenzio altrove;
|
||||
- `bar` → barra anche con output rediretto;
|
||||
- `plain` → una riga ogni 10% (per log e cron, senza disegno);
|
||||
- `off` → disattivata;
|
||||
- **nessun codice ANSI**: solo `\r` e riempimento con spazi, quindi funziona anche su
|
||||
console vecchie e seriali; glifi ASCII (`#`/`-`) se la locale non è UTF-8, blocchi
|
||||
Unicode (`█`/`░`) se lo è;
|
||||
- larghezza adattata al terminale (`TIOCGWINSZ`, fallback 80 colonne, max 200) e misurata
|
||||
in **colonne**, non in byte (i glifi UTF-8 sono multi-byte);
|
||||
- ridisegno limitato a ~8 volte al secondo, velocità con media mobile, ETA mostrata solo
|
||||
quando la stima è affidabile;
|
||||
- `CELLAR_PROGRESS_DEBUG=1` stampa su stderr modalità/larghezza calcolate (diagnostica).
|
||||
|
||||
```bash
|
||||
CELLAR_PROGRESS=plain cellar-cli install 'Gioco' # output adatto a un log
|
||||
CELLAR_PROGRESS=off cellar-cli install 'Gioco' # nessuna barra
|
||||
```
|
||||
|
||||
## Retrocompatibilità (le scelte che contano)
|
||||
|
||||
- **Binario statico** (`-static`): nessuna dipendenza da glibc a runtime, quindi gira su
|
||||
@@ -128,6 +159,7 @@ sei casi di errore di argomenti, più verifiche sugli artefatti:
|
||||
| Confronto nomi case-insensitive | ASCII (`tolower`) invece di `str.lower()` Unicode |
|
||||
| EOF su una richiesta interattiva | Python solleva `EOFError` (exit 1); qui si stampa `EOFError: EOF when reading a line` e si esce **1**. Nei prompt con default (nome archivio, descrizione…) su EOF si applica il default, così i wizard restano usabili da script |
|
||||
| Upload multipart | In **streaming** (il client Python legge l'intero archivio in RAM) |
|
||||
| Barra di avanzamento | Aggiunta (il CLI Python non stampa nulla durante download/estrazione). Attiva solo su terminale, quindi l'output rediretto resta identico all'originale |
|
||||
| TLS | Non supportato (niente OpenSSL): serve `http://`, oppure un reverse proxy TLS. Il server Cellar è HTTP |
|
||||
| Timeout di rete | Connect 15 s, I/O 300 s (urllib non ha timeout) |
|
||||
| Redirect | Seguiti come `urllib.request`: GET/HEAD su 301/302/303/307/308, POST→GET su 301/302/303 |
|
||||
@@ -135,11 +167,17 @@ sei casi di errore di argomenti, più verifiche sugli artefatti:
|
||||
## Test e verifica
|
||||
|
||||
```bash
|
||||
make test # parità (usa la build ASan)
|
||||
C_BIN=dist/cellar-cli tests/parity_test.sh # parità con il binario statico
|
||||
make verify # file/ldd/ABI/simboli GLIBC/syscall/smoke test
|
||||
make test # parità + barra (build ASan)
|
||||
C_BIN=dist/cellar-cli tests/parity_test.sh # parità con il binario statico
|
||||
C_BIN=dist/cellar-cli tests/progress_test.sh # barra: pipe silenziosa, PTY, plain, off
|
||||
make verify # file/ldd/ABI/simboli GLIBC/syscall/smoke test
|
||||
```
|
||||
|
||||
`tests/progress_test.sh` usa un server mock con throttling (`--throttle` byte/s) e
|
||||
`script -qec` per allocare un PTY: verifica che su pipe non ci sia alcun output di
|
||||
progresso, che su terminale compaiano le due fasi con ETA e riepilogo, che nessuna riga
|
||||
superi la larghezza del terminale e che non ci siano codici ANSI.
|
||||
|
||||
## Struttura
|
||||
|
||||
```
|
||||
@@ -154,6 +192,7 @@ src/config.{c,h} ~/.cellar.conf (INI in stile configparser)
|
||||
src/bottle.{c,h} record archivi, scansione bottiglie, bottle.yml, backup
|
||||
src/ui.{c,h} tabelle e JSON con larghezze in code point (come le f-string)
|
||||
src/ops.{c,h} list/upload/download/install
|
||||
src/progress.{c,h} barra di avanzamento (download + estrazione, env CELLAR_PROGRESS)
|
||||
src/wizard.{c,h} flussi interattivi
|
||||
src/main.c CLI e messaggi di errore in stile argparse
|
||||
third_party/ miniz (unlicense/MIT) + licenza
|
||||
|
||||
Reference in New Issue
Block a user