diff --git a/README.md b/README.md index afa8a70..3b7b709 100644 --- a/README.md +++ b/README.md @@ -147,10 +147,16 @@ Note: These are loaded in this order by '$ENV:CMDER_ROOT\\vendor\\user-profile.p ### SSH Agent -To start SSH agent simply call `start-ssh-agent`, which is in the `vendor/git-for-windows/cmd` folder. +To start the vendored SSH agent simply call `start-ssh-agent`, which is in the `vendor/git-for-windows/cmd` folder. If you want to run SSH agent on startup, include the line `@call "%GIT_INSTALL_ROOT%/cmd/start-ssh-agent.cmd"` in `%CMDER_ROOT%/config/user-profile.cmd` (usually just uncomment it). +### Vendored Git + +Cmder is by default shipped with a vendored Git installation. On each instance of launching Cmder, an attempt is made to locate any other user provided Git binaries. Upon finding a `git.exe` binary, Cmder further compares its version against the vendored one _by executing_ it. The vendored `git.exe` binary is _only_ used when it is more recent than the user-installed one. + +You may use your favorite version of Git by including its path in the `%PATH%` enviroment variable. Moreover, the **Mini** edition of Cmder (found on the [downloads page](https://github.com/cmderdev/cmder/releases)) excludes any vendored Git binaries. + ### Using external Cygwin/Babun, MSys2, or Git for Windows SDK with Cmder. 1. Setup a new task by pressing 'Win +Alt + T'. diff --git a/vendor/init.bat b/vendor/init.bat index 74334b4..8952cf5 100644 --- a/vendor/init.bat +++ b/vendor/init.bat @@ -47,26 +47,54 @@ if not defined TERM set TERM=cygwin :: * if the users points as to a specific git, use that :: * test if a git is in path and if yes, use that :: * last, use our vendored git -:: also check that we have a recent enough version of git (e.g. test for GIT\cmd\git.exe) +:: also check that we have a recent enough version of git by examining the version string if defined GIT_INSTALL_ROOT ( if exist "%GIT_INSTALL_ROOT%\cmd\git.exe" (goto :FOUND_GIT) ) +:: get the version information for vendored git binary +setlocal enabledelayedexpansion +call :read_version VENDORED "%CMDER_ROOT%\vendor\git-for-windows\cmd" + :: check if git is in path... setlocal enabledelayedexpansion for /F "delims=" %%F in ('where git.exe 2^>nul') do @( + + :: get the absolute path to the user provided git binary pushd %%~dpF - cd .. set "test_dir=!CD!" popd - if exist "!test_dir!\cmd\git.exe" ( - set "GIT_INSTALL_ROOT=!test_dir!" - set test_dir= - goto :FOUND_GIT + + :: get the version information for the user provided git binary + setlocal enabledelayedexpansion + call :read_version USER !test_dir! + + if !errorlevel! geq 0 ( + + :: compare the user git version against the vendored version + setlocal enabledelayedexpansion + call :compare_versions USER VENDORED + + :: use the user provided git if its version is greater than, or equal to the vendored git + if !errorlevel! geq 0 ( + set "GIT_INSTALL_ROOT=!test_dir!" + set test_dir= + goto :FOUND_GIT + ) else ( + echo Found old !GIT_VERSION_USER! in "!test_dir!", but not using... + set test_dir= + ) + ) else ( - echo Found old git version in "!test_dir!", but not using... - set test_dir= + + :: if the user provided git executable is not found + if !errorlevel! equ -255 ( + echo No git at "!git_executable!" found. + set test_dir= + ) + ) + ) :: our last hope: our own git... @@ -191,3 +219,91 @@ exit /b :verbose-output if %verbose-output% gtr 0 echo %* exit /b + +:: +:: specific to git version comparing +:: +:read_version + + :: clear the variables + set GIT_VERSION_%~1= + + :: set the executable path + set "git_executable=%~2\git.exe" + + :: check if the executable actually exists + if not exist "%git_executable%" ( + :: return a negative error code if the executable doesn't exist + exit /b -255 + ) + + :: get the git version in the provided directory + for /F "delims=" %%F in ('%git_executable% --version 2^>nul') do @( + set "GIT_VERSION_%~1=%%F" + ) + + :: parse the returned string + call :validate_version "%~1" !GIT_VERSION_%~1! + +goto :eof + +:parse_version + + :: process a `git version x.x.x.xxxx.x` formatted string + for /F "tokens=1-3* delims=.,-" %%A in ("%2") do ( + set "%~1_MAJOR=%%A" + set "%~1_MINOR=%%B" + set "%~1_PATCH=%%C" + set "%~1_BUILD=%%D" + ) + +goto :eof + +:validate_version + + :: check if we have a valid version string + if /I "%~2 %~3"=="GIT VERSION" ( + + :: now parse the version information into the corresponding variables + call :parse_version %~1 %~4 + + :: ... and maybe display it, for debugging purposes. + call :verbose-output Found Git Version for %~1: !%~1_MAJOR!.!%~1_MINOR!.!%~1_PATCH!.!%~1_BUILD! + + ) else ( + :: invalid format returned, use the vendored git instead + echo Invalid git version at "%git_executable%" detected! + call :verbose-output Returned version: %~2 %~3 %~4 + + rem or directly call the VENDORED_GIT + set test_dir= + exit /b -127 + ) + +goto :eof + +:compare_versions + + :: checks all major, minor, patch and build variables for the given arguments. + :: whichever binary that has the most recent version will be used based on the return code. + + :: call :verbose-output Comparing: + :: call :verbose-output %~1: !%~1_MAJOR!.!%~1_MINOR!.!%~1_PATCH!.!%~1_BUILD! + :: call :verbose-output %~2: !%~2_MAJOR!.!%~2_MINOR!.!%~2_PATCH!.!%~2_BUILD! + + if !%~1_MAJOR! GTR !%~2_MAJOR! (exit /b 1) + if !%~1_MAJOR! LSS !%~2_MAJOR! (exit /b -1) + + if !%~1_MINOR! GTR !%~2_MINOR! (exit /b 1) + if !%~1_MINOR! LSS !%~2_MINOR! (exit /b -1) + + if !%~1_PATCH! GTR !%~2_PATCH! (exit /b 1) + if !%~1_PATCH! LSS !%~2_PATCH! (exit /b -1) + + if !%~1_BUILD! GTR !%~2_BUILD! (exit /b 1) + if !%~1_BUILD! LSS !%~2_BUILD! (exit /b -1) + + :: looks like we have the same versions. + exit /b 0 + +goto :eof