1@echo off
2
3setLocal EnableExtensions EnableDelayedExpansion
4
5set LEIN_VERSION=2.9.8
6
7if "%LEIN_VERSION:~-9%" == "-SNAPSHOT" (
8    set SNAPSHOT=YES
9) else (
10    set SNAPSHOT=NO
11)
12
13set ORIGINAL_PWD=%CD%
14:: If ORIGINAL_PWD ends with a backslash (such as C:\),
15:: we need to escape it with a second backslash.
16if "%ORIGINAL_PWD:~-1%x" == "\x" set "ORIGINAL_PWD=%ORIGINAL_PWD%\"
17
18call :FIND_DIR_CONTAINING_UPWARDS project.clj
19if "%DIR_CONTAINING%" neq "" cd "%DIR_CONTAINING%"
20
21:: LEIN_JAR and LEIN_HOME variables can be set manually.
22:: Only set LEIN_JAR manually if you know what you are doing.
23:: Having LEIN_JAR pointing to one version of Leiningen as well as
24:: having a different version in PATH has been known to cause problems.
25
26if "x%LEIN_HOME%" == "x" (
27    set LEIN_HOME=!USERPROFILE!\.lein
28)
29SET RC=1
30
31if "x%LEIN_JAR%" == "x" set "LEIN_JAR=!LEIN_HOME!\self-installs\leiningen-!LEIN_VERSION!-standalone.jar"
32
33if "%1" == "self-install" goto SELF_INSTALL
34if "%1" == "upgrade"      goto UPGRADE
35if "%1" == "downgrade"    goto UPGRADE
36
37if not exist "%~dp0..\src\leiningen\version.clj" goto RUN_NO_CHECKOUT
38
39    :: Running from source checkout.
40    call :SET_LEIN_ROOT "%~dp0.."
41
42
43	set "bootstrapfile=!LEIN_ROOT!\leiningen-core\.lein-bootstrap"
44	rem in .lein-bootstrap there is only one line where each path is concatenated to each other via a semicolon, there's no semicolon at the end
45	rem each path is NOT inside double quotes and may contain spaces (even semicolons but this is not supported here) in their names,
46	rem  but they won't/cannot contain double quotes " or colons :  in their names (at least on windows it's not allowed/won't work)
47
48	rem tested when folders contain spaces and when LEIN_ROOT contains semicolon
49
50
51	if not "x%DEBUG%" == "x" echo LEIN_ROOT=!LEIN_ROOT!
52
53	rem if not "%LEIN_ROOT:;=%" == "%LEIN_ROOT%" (
54
55
56	rem oddly enough /G:/ should've worked but doesn't where / they say it's console
57	rem findstr is C:\Windows\System32\findstr.exe
58	echo.!LEIN_ROOT! | findstr /C:";" >nul 2>&1 && (
59		rem aka errorlevel is 0 aka the string ";" was found
60		echo Your folder structure !LEIN_ROOT! contains at least one semicolon in its name
61		echo This is not allowed and would break things with the generated bootstrap file
62		echo Please correct this by renaming the folders to not contain semicolons in their name
63		del !bootstrapfile! >nul 2>&1
64		echo You'll also have to recreate the bootstrap file just to be sure it has semicolon-free names inside
65		echo the bootstrap file ^(which was just deleted^) is: !bootstrapfile!
66		echo  and the info on how to do that is:
67		goto RUN_BOOTSTRAP
68	)
69
70	if not exist !bootstrapfile! goto NO_DEPENDENCIES
71
72	findstr \^" "!bootstrapfile!" >nul 2>&1
73	if errorlevel 1 goto PARSE_BOOTSTRAPFILE
74		echo double quotes detected inside file: !bootstrapfile!
75		echo this should not be happening
76		goto RUN_BOOTSTRAP
77
78:PARSE_BOOTSTRAPFILE
79rem will proceed to set LEIN_LIBS and surround each path from bootstrap file in double quotes and separate it from others with a semicolon
80rem the paths inside the bootstrap file do not already contain double quotes but may contain spaces
81	rem note worthy: the following won't work due to a hard 1022bytes limit truncation in the variable that was set
82	rem set /p LEIN_LIBS=<!bootstrapfile!
83	rem so this will work instead:
84	rem for /f "usebackq delims=" %%j in (!bootstrapfile!) do set LEIN_LIBS=%%j
85	rem just  set LEIN_LIBS="%%j"  is uglier/hacky but would also work here instead of the below:
86	for /f "usebackq delims=" %%j in ("!bootstrapfile!") do (
87		set tmpline=%%j
88		call :PROCESSPATH
89	)
90
91	rem remove trailing semicolon, if any
92	if "!LEIN_LIBS:~-1!x" == ";x" SET LEIN_LIBS=!LEIN_LIBS:~0,-1!
93	if not "x%DEBUG%" == "x" echo LEIN_LIBS=!LEIN_LIBS!
94
95    if "x!LEIN_LIBS!" == "x" goto NO_DEPENDENCIES
96
97
98	rem semicolons in pathes are not supported, spaces are supported by quoting CLASSPATH as a whole
99	rem (no end semicolon required)
100    set CLASSPATH=!LEIN_LIBS!;!LEIN_ROOT!\src;!LEIN_ROOT!\resources
101
102    :: Apply context specific CLASSPATH entries
103    if exist "%~dp0..\.lein-classpath" (
104        for /f "tokens=* delims= " %%i in ("%~dp0..\.lein-classpath") do (
105            set CONTEXT_CP=%%i
106        )
107
108        if NOT "x!CONTEXT_CP!"=="x" (
109            set CLASSPATH=!CONTEXT_CP!;!CLASSPATH!
110        )
111    )
112    goto SETUP_JAVA
113
114:RUN_NO_CHECKOUT
115
116    :: Not running from a checkout.
117    if not exist "%LEIN_JAR%" goto NO_LEIN_JAR
118    set CLASSPATH=%LEIN_JAR%
119
120    if exist ".lein-classpath" (
121        for /f "tokens=* delims= " %%i in (.lein-classpath) do (
122            set CONTEXT_CP=%%i
123        )
124
125        if NOT "x!CONTEXT_CP!"=="x" (
126            set CLASSPATH=!CONTEXT_CP!;!CLASSPATH!
127        )
128    )
129
130:SETUP_JAVA
131
132if not "x%DEBUG%" == "x" echo CLASSPATH=!CLASSPATH!
133:: ##################################################
134
135if "x!JAVA_CMD!" == "x" set JAVA_CMD=java
136if "x!LEIN_JAVA_CMD!" == "x" set LEIN_JAVA_CMD=%JAVA_CMD%
137
138rem remove quotes from around java commands
139for /f "usebackq delims=" %%i in ('!JAVA_CMD!') do set JAVA_CMD=%%~i
140for /f "usebackq delims=" %%i in ('!LEIN_JAVA_CMD!') do set LEIN_JAVA_CMD=%%~i
141
142if "x%JVM_OPTS%" == "x" set JVM_OPTS=%JAVA_OPTS%
143goto RUN
144
145:DownloadFile
146set LAST_HTTP_CLIENT=
147rem parameters: TargetFileName Address
148if "x%HTTP_CLIENT%" == "x" goto TRY_POWERSHELL
149    %HTTP_CLIENT% %1 %2
150    SET RC=%ERRORLEVEL%
151    goto EXITRC
152
153:TRY_POWERSHELL
154call powershell -? >nul 2>&1
155if NOT ERRORLEVEL 0 goto TRY_WGET
156    set LAST_HTTP_CLIENT=powershell
157    rem By default: Win7 = PS2, Win 8.0 = PS3 (maybe?), Win 8.1 = PS4, Win10 = PS5
158    powershell -Command "& {param($a,$f) if (($PSVersionTable.PSVersion | Select-Object -ExpandProperty Major) -lt 4) { exit 111; } else { $client = New-Object System.Net.WebClient; [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $client.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials; $client.DownloadFile($a, $f); }}" ""%2"" ""%1""
159    SET RC=%ERRORLEVEL%
160    goto EXITRC
161
162:TRY_WGET
163call wget --help >nul 2>&1
164if NOT ERRORLEVEL 0 goto TRY_CURL
165    set LAST_HTTP_CLIENT=wget
166    call wget -O %1 %2
167    SET RC=%ERRORLEVEL%
168    goto EXITRC
169
170:TRY_CURL
171call curl --help >nul 2>&1
172if NOT ERRORLEVEL 0 GOTO NO_HTTP_CLIENT
173    rem We set CURL_PROXY to a space character below to pose as a no-op argument
174    set LAST_HTTP_CLIENT=curl
175    set CURL_PROXY=
176    if NOT "x%HTTPS_PROXY%" == "x" set CURL_PROXY="-x %HTTPS_PROXY%"
177    call curl %CURL_PROXY% -f -L -o  %1 %2
178    SET RC=%ERRORLEVEL%
179    goto EXITRC
180
181:NO_LEIN_JAR
182echo.
183echo %LEIN_JAR% can not be found.
184echo You can try running "lein self-install"
185echo or change LEIN_JAR environment variable
186echo or edit lein.bat to set appropriate LEIN_JAR path.
187echo.
188goto EXITRC
189
190:NO_DEPENDENCIES
191echo.
192echo Leiningen is missing its dependencies.
193:RUN_BOOTSTRAP
194echo Please run "lein bootstrap" in the leiningen-core/ directory
195echo with a stable release of Leiningen. See CONTRIBUTING.md for details.
196echo.
197goto EXITRC
198
199:SELF_INSTALL
200if exist "%LEIN_JAR%" (
201    echo %LEIN_JAR% already exists. Delete and retry.
202    goto EXITRC
203)
204
205for %%f in ("%LEIN_JAR%") do set LEIN_INSTALL_DIR="%%~dpf"
206if not exist %LEIN_INSTALL_DIR% mkdir %LEIN_INSTALL_DIR%
207
208echo Downloading Leiningen now...
209
210set LEIN_JAR_URL=https://github.com/technomancy/leiningen/releases/download/%LEIN_VERSION%/leiningen-%LEIN_VERSION%-standalone.jar
211call :DownloadFile "%LEIN_JAR%.pending" "%LEIN_JAR_URL%"
212SET RC=%ERRORLEVEL%
213if not %RC% == 0 goto DOWNLOAD_FAILED
214if not exist "%LEIN_JAR%.pending" goto DOWNLOAD_FAILED
215move /y "%LEIN_JAR%.pending" "%LEIN_JAR%" >nul 2>&1
216SET RC=%ERRORLEVEL%
217goto EXITRC
218
219:DOWNLOAD_FAILED
220SET RC=3
221if "%ERRORLEVEL%" == "111" (
222    echo.
223    echo You seem to be using an old version of PowerShell that
224    echo can't download files via TLS 1.2.
225    echo Please upgrade your PowerShell to at least version 4.0, e.g. via
226    echo https://www.microsoft.com/en-us/download/details.aspx?id=50395
227    echo.
228    echo Alternatively you can manually download
229    echo %LEIN_JAR_URL%
230    echo and save it as
231    echo %LEIN_JAR%
232    echo.
233    echo If you have "curl" or "wget" you can try setting the HTTP_CLIENT
234    echo variable, but the TLS problem might still persist.
235    echo.
236    echo   a^) set HTTP_CLIENT=wget -O
237    echo   b^) set HTTP_CLIENT=curl -f -L -o
238    echo.
239    echo NOTE: Make sure to *not* add double quotes when setting the value
240    echo       of HTTP_CLIENT
241    goto EXITRC
242)
243SET RC=3
244del "%LEIN_JAR%.pending" >nul 2>&1
245echo.
246echo Failed to download %LEIN_JAR_URL%
247echo.
248echo It is possible that the download failed due to "powershell",
249echo "curl" or "wget"'s inability to retrieve GitHub's security certificate.
250echo.
251
252if "%LAST_HTTP_CLIENT%" == "powershell" (
253  echo The PowerShell failed to download the latest Leiningen version.
254  echo Try to use "curl" or "wget" to download Leiningen by setting up
255  echo the HTTP_CLIENT environment variable with one of the following
256  echo values:
257  echo.
258  echo   a^) set HTTP_CLIENT=wget -O
259  echo   b^) set HTTP_CLIENT=curl -f -L -o
260  echo.
261  echo NOTE: Make sure to *not* add double quotes when setting the value
262  echo       of HTTP_CLIENT
263)
264
265if "%LAST_HTTP_CLIENT%" == "curl" (
266  echo Curl failed to download the latest Leiningen version.
267  echo Try to use "wget" to download Leiningen by setting up
268  echo the HTTP_CLIENT environment variable with one of the following
269  echo values:
270  echo.
271  echo   a^) set HTTP_CLIENT=wget -O
272  echo.
273  echo NOTE: Make sure to *not* add double quotes when setting the value
274  echo       of HTTP_CLIENT
275  echo.
276  echo If neither curl nor wget can download Leiningen, please seek
277  echo for help on Leiningen's GitHub project issues page.
278)
279
280if "%LAST_HTTP_CLIENT%" == "wget" (
281  echo Curl failed to download the latest Leiningen version.
282  echo Try to use "wget" to download Leiningen by setting up
283  echo the HTTP_CLIENT environment variable with one of the following
284  echo values:
285  echo.
286  echo.   a^) set HTTP_CLIENT=curl -f -L -o
287  echo.
288  echo NOTE: make sure *not* to add double quotes to set the value of
289  echo       HTTP_CLIENT
290  echo.
291  echo If neither curl nor wget can download Leiningen, please seek
292  echo for help on Leiningen's GitHub project issues page.
293)
294
295if %SNAPSHOT% == YES echo See README.md for SNAPSHOT build instructions.
296echo.
297goto EOF
298
299
300:UPGRADE
301set LEIN_BAT=%~dp0%~nx0
302set TARGET_VERSION=%2
303if "x%2" == "x" set TARGET_VERSION=stable
304echo The script at %LEIN_BAT% will be upgraded to the latest %TARGET_VERSION% version.
305set /P ANSWER=Do you want to continue (Y/N)?
306if /i {%ANSWER%}=={y}   goto YES_UPGRADE
307if /i {%ANSWER%}=={yes} goto YES_UPGRADE
308echo Aborted.
309goto EXITRC
310
311
312:YES_UPGRADE
313echo Downloading latest Leiningen batch script...
314
315set LEIN_BAT_URL=https://github.com/technomancy/leiningen/raw/%TARGET_VERSION%/bin/lein.bat
316set TEMP_BAT=%~dp0temp-lein-%RANDOM%%RANDOM%.bat
317call :DownloadFile "%LEIN_BAT%.pending" "%LEIN_BAT_URL%"
318if ERRORLEVEL 0 goto EXEC_UPGRADE
319    del "%LEIN_BAT%.pending" >nul 2>&1
320    echo Failed to download %LEIN_BAT_URL%
321    goto EXITRC
322:EXEC_UPGRADE
323move /y "%LEIN_BAT%.pending" "%TEMP_BAT%" >nul 2>&1
324echo.
325echo Upgrading...
326set LEIN_JAR=
327call "%TEMP_BAT%" self-install
328(
329   rem This is self-modifying batch code. Use brackets to pre-load the exit command.
330   rem This way, script execution does not depend on whether the replacement script
331   rem has that command at the *very same* file position as the calling batch file.
332   move /y "%TEMP_BAT%" "%LEIN_BAT%" >nul 2>&1
333   exit /B %ERRORLEVEL%
334)
335
336:NO_HTTP_CLIENT
337echo.
338echo ERROR: Neither PowerShell, Wget, or Curl could be found.
339echo        Make sure at least one of these tools is installed
340echo        and is in PATH. You can get them from URLs below:
341echo.
342echo PowerShell: "http://www.microsoft.com/powershell"
343
344rem echo Wget:       "http://users.ugent.be/~bpuype/wget/"
345rem Note: Stale URL. HTTP 404.
346rem Alternative: wget64.exe compiled by J. Simoncic, rename to wget.exe
347rem MD5 1750c130c5daca8b347d3f7e34824c9b
348rem Check: https://www.virustotal.com/en/file/abf507f8240ed41aac74c9df6de558c88c2f11d7770f02.8.4-SNAPSHOT5f1cc544b9c08b/analysis/
349echo Wget:       "https://eternallybored.org/misc/wget/"
350
351echo Curl:       "http://curl.haxx.se/dlwiz/?type=bin&os=Win32&flav=-&ver=2000/XP"
352echo.
353goto EXITRC
354
355
356:SET_LEIN_ROOT
357set LEIN_ROOT=%~f1
358goto EOF
359
360:: Find directory containing filename supplied in first argument
361:: looking in current directory, and looking up the parent
362:: chain until we find it, or run out
363:: returns result in %DIR_CONTAINING%
364:: empty string if we don't find it
365:FIND_DIR_CONTAINING_UPWARDS
366set DIR_CONTAINING=%CD%
367set LAST_DIR=
368
369:LOOK_AGAIN
370if "%DIR_CONTAINING%" == "%LAST_DIR%" (
371    :: didn't find it
372    set DIR_CONTAINING=
373    goto EOF
374)
375
376if EXIST "%DIR_CONTAINING%\%1" (
377    :: found it - use result in DIR_CONTAINING
378    goto EOF
379)
380
381set LAST_DIR=%DIR_CONTAINING%
382call :GET_PARENT_PATH "%DIR_CONTAINING%\.."
383set DIR_CONTAINING=%PARENT_PATH%
384goto LOOK_AGAIN
385
386:GET_PARENT_PATH
387set PARENT_PATH=%~f1
388goto EOF
389
390
391:RUN
392:: We need to disable delayed expansion here because the %* variable
393:: may contain bangs (as in test!). There may also be special
394:: characters inside the TRAMPOLINE_FILE.
395setLocal DisableDelayedExpansion
396
397set "TRAMPOLINE_FILE=%TEMP%\lein-trampoline-%RANDOM%.bat"
398del "%TRAMPOLINE_FILE%" >nul 2>&1
399
400set ERRORLEVEL=
401set RC=0
402"%LEIN_JAVA_CMD%" -client %LEIN_JVM_OPTS% ^
403 -Dfile.encoding=UTF-8 ^
404 -Dclojure.compile.path="%DIR_CONTAINING%/target/classes" ^
405 -Dleiningen.original.pwd="%ORIGINAL_PWD%" ^
406 -cp "%CLASSPATH%" clojure.main -m leiningen.core.main %*
407SET RC=%ERRORLEVEL%
408if not %RC% == 0 goto EXITRC
409
410if not exist "%TRAMPOLINE_FILE%" goto EOF
411call "%TRAMPOLINE_FILE%"
412del "%TRAMPOLINE_FILE%" >nul 2>&1
413goto EOF
414
415
416:PROCESSPATH
417rem will surround each path with double quotes before appending it to LEIN_LIBS
418	for /f "tokens=1* delims=;" %%a in ("%tmpline%") do (
419		set LEIN_LIBS=!LEIN_LIBS!"%%a";
420		set tmpline=%%b
421	)
422	if not "%tmpline%" == "" goto PROCESSPATH
423	goto EOF
424
425:EXITRC
426exit /B %RC%
427
428:EOF
429
430