Repository navigation
Expand file tree
/
Copy pathopencode-portable.cmd
More file actions
173 lines (161 loc) · 8.48 KB
/
Copy pathopencode-portable.cmd
File metadata and controls
173 lines (161 loc) · 8.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
@ECHO OFF
SETLOCAL
REM ============================================================
REM Opencode Portable launcher (Windows)
REM Config, dati, cache e log restano dentro la cartella
REM portable (.\data). Niente in %USERPROFILE%\.config o
REM %USERPROFILE%\.local\share.
REM ============================================================
REM Cartella che contiene questo script (senza backslash finale, ma mai
REM ridotta a lettera drive nuda: "C:\" deve restare "C:\", non "C:")
SET "ROOT=%~dp0"
IF "%ROOT%"=="%~d0\" SET "ROOT=%~d0\"
IF NOT "%ROOT%"=="%~d0\" IF "%ROOT:~-1%"=="\" SET "ROOT=%ROOT:~0,-1%"
SET "DATA=%ROOT%\data"
IF NOT EXIST "%DATA%\config" MKDIR "%DATA%\config"
IF NOT EXIST "%DATA%\data" MKDIR "%DATA%\data"
IF NOT EXIST "%DATA%\cache" MKDIR "%DATA%\cache"
IF NOT EXIST "%DATA%\state" MKDIR "%DATA%\state"
SET "TMPROOT=%DATA%\tmp"
IF NOT EXIST "%TMPROOT%" MKDIR "%TMPROOT%"
REM Prima esecuzione: crea config da template se manca (fresh clone)
IF NOT EXIST "%ROOT%\config\opencode.json" IF EXIST "%ROOT%\config\opencode.example.json" COPY /Y "%ROOT%\config\opencode.example.json" "%ROOT%\config\opencode.json" >NUL
REM Redirect di config / dati / cache dentro .\data
SET "XDG_CONFIG_HOME=%DATA%\config"
SET "XDG_DATA_HOME=%DATA%\data"
SET "XDG_CACHE_HOME=%DATA%\cache"
SET "XDG_STATE_HOME=%DATA%\state"
SET "OPENCODE_CONFIG=%ROOT%\config\opencode.json"
REM Niente fetch bloccante di models.dev all'avvio (10-30s): usa cache/integrato
SET "OPENCODE_DISABLE_MODELS_FETCH=1"
REM Foto della temp di sistema PRIMA del redirect (guard: cancello solo cio che nasce in questa run)
SET "SYS_TMP=%TEMP%"
SET "SYS_OPENC=%SYS_TMP%\opencode"
IF EXIST "%SYS_OPENC%" (SET "SYS_OPENC_EXISTS=1") ELSE (SET "SYS_OPENC_EXISTS=0")
SET "SYS_LOCAL_OPENC=%LOCALAPPDATA%\opencode"
IF EXIST "%SYS_LOCAL_OPENC%" (SET "SYS_LOCAL_EXISTS=1") ELSE (SET "SYS_LOCAL_EXISTS=0")
SET "SYS_ROAM_OPENC=%APPDATA%\opencode"
IF EXIST "%SYS_ROAM_OPENC%" (SET "SYS_ROAM_EXISTS=1") ELSE (SET "SYS_ROAM_EXISTS=0")
REM Fallback auth di opencode quando XDG_DATA_HOME manca (~/.opencode/auth.json):
REM lo impostiamo sempre, ma un figlio che ignora i redirect potrebbe scriverci.
SET "SYS_HOME_OPENC=%USERPROFILE%\.opencode"
IF EXIST "%SYS_HOME_OPENC%" (SET "SYS_HOME_EXISTS=1") ELSE (SET "SYS_HOME_EXISTS=0")
REM Risoluzione binario PRIMA di creare tmp: le uscite anticipate (binario
REM mancante) non lasciano directory temporanee.
REM EXE bundled. Fallback a opencode da PATH SOLO con opt-in esplicito
REM (--from-path ovunque tra gli argomenti, o OPENCODE_ALLOW_PATH_FALLBACK=1):
REM senza opt-in un eseguibile omonimo nel PATH verrebbe lanciato in silenzio.
SET "BIN=%ROOT%\bin\opencode.exe"
SET "ALLOW_PATH=0"
IF /I "%OPENCODE_ALLOW_PATH_FALLBACK%"=="1" SET "ALLOW_PATH=1"
REM Ricostruisci gli argomenti togliendo --from-path (ovunque sia): SHIFT non
REM tocca %*, quindi %* inoltrerebbe il flag al figlio. Re-quoting uniforme.
REM NOTA fedeltà: metacaratteri grezzi (& | ^) e stringhe vuote negli argomenti
REM CLI possono alterarsi/troncarsi in transito (limite di cmd.exe, non aggirabile
REM in puro batch); per argomenti esotici usare opencode-portable.ps1 (exact).
SET "FWD="
:argloop
IF "%~1"=="" GOTO :argdone
IF "%~1"=="--from-path" (SET "ALLOW_PATH=1" & SHIFT /1 & GOTO :argloop)
SET "FWD=%FWD% "%~1""
SHIFT /1
GOTO :argloop
:argdone
IF EXIST "%BIN%" GOTO :runbin
IF "%ALLOW_PATH%"=="0" (
ECHO [opencode-portable] ERRORE: "%BIN%" non trovato.
ECHO [opencode-portable] Esegui scripts\setup.ps1 per scaricarlo, oppure riusa opencode da PATH con --from-path o OPENCODE_ALLOW_PATH_FALLBACK=1.
ENDLOCAL & EXIT /B 1
)
WHERE opencode >NUL 2>&1
IF ERRORLEVEL 1 (
ECHO [opencode-portable] ERRORE: nessun opencode in PATH.
ENDLOCAL & EXIT /B 1
)
SET "BIN_FROM_PATH="
FOR /F "delims=" %%B IN ('WHERE opencode 2^>NUL') DO IF NOT DEFINED BIN_FROM_PATH SET "BIN_FROM_PATH=%%B"
IF NOT DEFINED BIN_FROM_PATH (
ECHO [opencode-portable] ERRORE: impossibile risolvere opencode in PATH.
ENDLOCAL & EXIT /B 1
)
SET "BIN=%BIN_FROM_PATH%"
ECHO [opencode-portable] ATTENZIONE: uso opencode da PATH: "%BIN%"
:runbin
REM Temp isolata per questa run (sicura anche con istanze concorrenti).
REM NOTA: %TIME% dipende dal locale (separatori diversi, spazi): sanitizza.
SET "RAWTIME=%TIME: =0%"
SET "RAWTIME=%RAWTIME:/=-%"
SET "RAWTIME=%RAWTIME:.=-%"
SET "RAWTIME=%RAWTIME:,=-%"
SET "RAWTIME=%RAWTIME:;=-%"
SET "RUNID=run-%RAWTIME:~0,2%%RAWTIME:~3,2%%RAWTIME:~6,2%%RAWTIME:~9,2%-%RANDOM%"
SET "RUN_TMP=%TMPROOT%\%RUNID%"
IF EXIST "%RUN_TMP%" SET "RUN_TMP=%TMPROOT%\%RUNID%-%RANDOM%"
IF EXIST "%RUN_TMP%" SET "RUN_TMP=%TMPROOT%\%RUNID%-%RANDOM%-%RANDOM%"
MKDIR "%RUN_TMP%" 2>NUL
SET "CLEAN_RUN_TMP=1"
IF NOT EXIST "%RUN_TMP%" SET "CLEAN_RUN_TMP=0"
IF "%CLEAN_RUN_TMP%"=="0" SET "RUN_TMP=%TMPROOT%"
REM Marchio di proprietà: solo le tmp con questo file vengono spazzate sotto.
REM Senza, lo sweeper per età non distinguerebbe le tmp vive degli altri
REM launcher (ps1/sh usano lo stesso prefisso run-*).
IF "%CLEAN_RUN_TMP%"=="1" TYPE NUL > "%RUN_TMP%\.portable-cmd" 2>NUL
REM Foto della tmp del portable (guard: opencode potrebbe scriverci una cartella "opencode")
SET "TMPROOT_OPENC=%TMPROOT%\opencode"
IF EXIST "%TMPROOT_OPENC%" (SET "TMPROOT_OPENC_EXISTS=1") ELSE (SET "TMPROOT_OPENC_EXISTS=0")
REM Sweeper: tmp di run morte da oltre 7 giorni (crash/kill). NOTA: cmd non
REM conosce il PID (niente liveness check come ps1/sh/exe): cancella solo le
REM dir col marchio .portable-cmd creato sopra, così non tocca mai le tmp
REM vive degli altri launcher. Resta la soglia di 7 giorni per non toccare
REM run recenti/concorrenti; una sessione cmd viva da oltre 7 giorni resta
REM un caso non supportato (usare ps1/exe per sessioni lunghissime).
FORFILES /P "%TMPROOT%" /M "run-*" /D -7 /C "CMD /C IF @isdir==TRUE IF EXIST \"%TMPROOT%\@fname\.portable-cmd\" RMDIR /S /Q @path" 2>NUL
REM Temp di opencode e processi figli nella tmp di questa run
SET "TMP=%RUN_TMP%"
SET "TEMP=%RUN_TMP%"
SET "TMPDIR=%RUN_TMP%"
REM Esegui il figlio. CALL per .cmd/.bat (senza, il controllo non torna e la
REM cleanup sotto non gira mai). Delayed expansion solo in questo blocco: così
REM i metacaratteri già quotati in FWD non vengono reinterpretati in uscita.
IF /I "%BIN:~-4%"==".cmd" GOTO :runcmd
IF /I "%BIN:~-4%"==".bat" GOTO :runcmd
SETLOCAL EnableDelayedExpansion
"!BIN!" !FWD!
SET "EXITCODE=!ERRORLEVEL!"
ENDLOCAL & SET "EXITCODE=%EXITCODE%"
GOTO :afterrun
:runcmd
SETLOCAL EnableDelayedExpansion
CALL "!BIN!" !FWD!
SET "EXITCODE=!ERRORLEVEL!"
ENDLOCAL & SET "EXITCODE=%EXITCODE%"
GOTO :afterrun
:afterrun
REM Cleanup best-effort della sola tmp di questa run (mai il codice d'uscita).
REM Retry breve: il runtime Bun mappa una sua DLL in TMPDIR e Defender scansiona
REM i file nuovi; un singolo RMDIR perderebbe la race contro questi lock
REM transitori. Fino a ~10s, poi i resti vanno allo sweeper al prossimo avvio.
SET "MARKER_CHECK=%RUN_TMP:\data\tmp\run-=%"
IF "%CLEAN_RUN_TMP%"=="1" IF NOT "%MARKER_CHECK%"=="%RUN_TMP%" IF EXIST "%RUN_TMP%" CALL :delretry "%RUN_TMP%"
IF "%TMPROOT_OPENC_EXISTS%"=="0" IF EXIST "%TMPROOT_OPENC%" RMDIR /S /Q "%TMPROOT_OPENC%" 2>NUL
REM Cartelle opencode fuori dal portable: solo se generate da questa run
REM (RMDIR per le dir, DEL per gli eventuali file: mirror di DeletePath)
REM Cartelle opencode fuori dal portable: solo se generate da questa run.
REM RMDIR per le dir (test via suffisso \NUL), DEL per i file: mirror di DeletePath.
IF DEFINED SYS_TMP IF "%SYS_OPENC_EXISTS%"=="0" IF EXIST "%SYS_OPENC%\NUL" (RMDIR /S /Q "%SYS_OPENC%" 2>NUL) ELSE IF EXIST "%SYS_OPENC%" DEL /F /Q "%SYS_OPENC%" 2>NUL
IF DEFINED LOCALAPPDATA IF "%SYS_LOCAL_EXISTS%"=="0" IF EXIST "%SYS_LOCAL_OPENC%\NUL" (RMDIR /S /Q "%SYS_LOCAL_OPENC%" 2>NUL) ELSE IF EXIST "%SYS_LOCAL_OPENC%" DEL /F /Q "%SYS_LOCAL_OPENC%" 2>NUL
IF DEFINED APPDATA IF "%SYS_ROAM_EXISTS%"=="0" IF EXIST "%SYS_ROAM_OPENC%\NUL" (RMDIR /S /Q "%SYS_ROAM_OPENC%" 2>NUL) ELSE IF EXIST "%SYS_ROAM_OPENC%" DEL /F /Q "%SYS_ROAM_OPENC%" 2>NUL
IF DEFINED USERPROFILE IF "%SYS_HOME_EXISTS%"=="0" IF EXIST "%SYS_HOME_OPENC%\NUL" (RMDIR /S /Q "%SYS_HOME_OPENC%" 2>NUL) ELSE IF EXIST "%SYS_HOME_OPENC%" DEL /F /Q "%SYS_HOME_OPENC%" 2>NUL
ENDLOCAL & EXIT /B %EXITCODE%
REM Sottoroutine di cancellazione con retry (chiamata solo da sopra, mai in
REM caduta libera: dopo EXIT non si torna). Non tocca mai EXITCODE.
:delretry
FOR /L %%R IN (1,1,10) DO (
IF NOT EXIST "%~1" GOTO :EOF
RMDIR /S /Q "%~1" 2>NUL
IF NOT EXIST "%~1" GOTO :EOF
REM Pausa ~1s senza dipendere da stdin/console: timeout.exe fallisce con
REM input ridirezionato (uso pipato, CI), mentre ping su loopback no.
ping -n 2 127.0.0.1 >NUL 2>&1
)
GOTO :EOF