@echo off rem Update script for TeX Live infrastructure rem called automatically if there are any infrastructure updates rem rem Copyright 2009 by Tomasz M. Trzeciak rem This file is licensed under the GNU General Public License version 2 rem or any later version. rem :: =================================================================== :: INFRASTRUCTURE UPDATE ON WINDOWS :: =================================================================== :: Infrastructure files cannot be updated directly from the tlmgr.pl :: script due to file locking problem on Windows - files that are in :: use (either open or executing) cannot be removed or replaced. :: Therefore the update process is performed by a batch script outside :: of tlmgr.pl. :: There are three pieces involved in the update: tlmgr.bat launcher, :: write_w32_updater subroutine in tlmgr.pl and this script. Their :: roles are as follows: :: * tlmgr.bat is a watchdog - it launches tlmgr.pl and watches for :: a trigger script that is to be executed. If trigger script exists :: before tlmgr.pl is launched, it will be removed or tlmgr.bat will :: abort if it fails to do so. This means that the trigger script :: has to be created by the current invocation of tlmgr.pl :: * write_w32_updater subroutine in tlmgr.pl prepares the update :: and writes the trigger script. Packages in .xz archives are :: dowloaded/copied and uncompressed to .tar files. Also .tar :: backups of the current packages are made. If everything is :: successful, the trigger script is written, otherwise the update :: is aborted. :: * run-updater-w32.bat trigger script passes package list together :: with revison numbers to the updater script. Additionally it locks :: itself up write open (and the updater script as well) to prevent :: tlmgr.bat from starting another instance of tlmgr and/or update. :: * updater-w32.bat, which is this script, does the actual update. It :: makes some very specific assumptions. Arguments are expected to :: be a package list passed in triples: :: package-name old-revision-number new-revision-number :: For each package-name a .tar archive package-name.tar is expected :: (also for .source and .doc pseudo packages---those are for :: distribution only and don't appear separately in tlpdb). :: Additionally a backup archive is expected: :: __BACKUP_package-name.rXXX.tar, :: where XXX is (old) revision number (.source and .doc are included :: in the backup). :: The update itself proceeds as follows: :: (1) untar all package archives :: (2) include .tlpobj files into tlpdb :: (3) print update info :: Any error during (1) or (2) triggers the rollback action: :: (1) print failed update info :: (2) untar all package backups :: (3) include .tlpobj files (from backup) into tlpdb :: (4) print restore info :: Any error during (2) or (3) and we go into panic mode. At this :: point there is no guarantee that the installation is still :: working. There is not much we can do but to print failed restore :: info and give instructions to download and run :: 'update-tlmgr-latest.exe' to repair the installation. :: =================================================================== rem Make environment changes local & enable cmd extensions rem (we don't want delayed expansion becasue it's hard to echo bang !) setlocal enableextensions disabledelayedexpansion rem Make sure that we can use dynamic variables (set errorlevel=) (set date=) (set time=) rem Get TL installation root for /f "delims=" %%I in ('kpsewhich -var-value=SELFAUTOPARENT') do (set tlroot=%%~fI) if not exist "%tlroot%\texmf\scripts\texlive\tlmgr.pl" ( echo %~n0: cannot locate installation root.>&2 exit /b 1 ) rem Get log file location for /f "delims=" %%I in ('kpsewhich -var-value=TEXMFSYSVAR') do (set logdir=%%~fI\web2c) if not exist "%logdir%\" (set logdir=%tlroot%\temp) rem Change to root rem cd /d "%tlroot%" rem Make a private copy of tar.exe copy /y "%tlroot%\tlpkg\installer\tar.exe" "%tlroot%\temp\tar-w32.exe" >nul if errorlevel 1 ( echo %~n0: cannot copy tar.exe.>&2 exit /b 1 ) rem Set up perl environment set PERL5LIB=%tlroot%\tlpkg\tlperl\lib rem Get package list from arguments (set pkgpartslist=%*) if not defined pkgpartslist ( echo %~n0: no arguments given, how did you start me?>&2 exit /b 1 ) rem Construct package list without .source and .doc packages rem Count the total number of packages while doing that set pkgcount=0 (set pkglist=) call :foreachpkg remove_src_doc pkglist %pkgpartslist% rem Set gui mode to console if not defined if not defined guimode set guimode=0 echo DO NOT CLOSE THIS WINDOW! echo TeX Live infrastructure update in progress... call :foreachpkg untar "%tlroot%\temp\" %pkgpartslist% if errorlevel 1 goto :rollback call :foreachpkg incltlpobj "%tlroot%\tlpkg\tlpobj\" %pkgpartslist% if errorlevel 1 goto :rollback call :foreachpkg updateinfo "update" %pkglist% call :printmsg%guimode% "TeX Live infrastructure update complete." 0 "TeX Live Manager 2008" set exitcode=0 goto :finish :rollback call :foreachpkg updateinfo "failed update" %pkglist% >&2 echo Rolling back to previous version... call :foreachpkg untar "%tlroot%\temp\__BACKUP_" %pkglist% if errorlevel 1 goto :panic call :foreachpkg incltlpobj "%tlroot%\tlpkg\tlpobj\" %pkglist% if errorlevel 1 goto :panic call :foreachpkg restoreinfo "restore" %pkglist% call :printmsg%guimode% "TeX Live infrastructure update failed.\nPrevious version has been restored." 16 "ERROR: TeX Live Manager 2008" >&2 set exitcode=1 goto :finish :panic call :foreachpkg restoreinfo "failed restore" %pkglist% >&2 call :printmsg%guimode% "TeX Live infrastructure update failed and backup recovery failed as well.\nYour TeX Live installation may be broken, to repair it download and run:\nhttp://mirror.ctan.org/systems/texlive/tlnet/2008/update-tlmgr-latest.exe" 16 "FATAL ERROR: TeX Live Manager 2008" >&2 rem Evil has taken over - emit adequate exit code exit /b 666 :finish del "%tlroot%\temp\tar-w32.exe" "%tlroot%\temp\__BACKUP_*" >nul 2>&1 exit /b %exitcode% REM SUBROUTINES :foreachpkg cmd prefix pkgname oldrev newrev ... set pkgnr=0 :pkgloop if [%3]==[] exit /b 0 call :%1 %2 %3 %4 %5 if errorlevel 1 exit /b 1 shift /3 & shift /3 & shift /3 goto :pkgloop :remove_src_doc if /i %~x2.==.source. exit /b 0 if /i %~x2.==.doc. exit /b 0 set %1=%pkglist% %2 %3 %4 set /a pkgcount+=1 exit /b 0 :untar %tlroot%\temp\[__BACKUP_] pkgname set "suffix=tar" if %~n1_==__BACKUP__ set "suffix=r%~3.tar" "%tlroot%\temp\tar-w32.exe" -C "%tlroot%" -f "%~1%~2.%suffix%" -x && del "%~1%~2.%suffix%" exit /b %errorlevel% :incltlpobj %tlroot%\tlpkg\tlpobj\ pkgname "%tlroot%\tlpkg\tlperl\bin\perl.exe" "%tlroot%\texmf\scripts\texlive\tlmgr.pl" _include_tlpobj "%~1%~2.tlpobj" exit /b %errorlevel% :updateinfo header pkgname oldrev newrev set "infomsg= -> %~4" :restoreinfo header pkgname oldrev newrev set "infomsg=%~1: %~2 (%~3%infomsg%)" set "infomsg=%infomsg:>=^>%" set /a pkgnr+=1 echo [%pkgnr%/%pkgcount%] %infomsg% echo [%date% %time%] %infomsg%>>"%logdir%\tlmgr.log" set "infomsg=" exit /b 0 :printmsg0 "message text" set infomsg=%~1 for %%I in ("%infomsg:\n=" "%") do echo.%%~I exit /b 0 :printmsg1 "message text" icon "title string" echo MsgBox Replace("%~1", "\n", Chr(10)), %2, "%~3" >"%tlroot%\temp\dialogpopup.vbs" cscript -nologo "%tlroot%\temp\dialogpopup.vbs" del "%tlroot%\temp\dialogpopup.vbs" exit /b %errorlevel%