summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xMaster/bin/win32/tlmgr.bat55
-rwxr-xr-xMaster/texmf/scripts/texlive/tlmgr.pl23
-rw-r--r--Master/texmf/scripts/texlive/updater-w32.bat236
3 files changed, 193 insertions, 121 deletions
diff --git a/Master/bin/win32/tlmgr.bat b/Master/bin/win32/tlmgr.bat
index eeb7a3bdf0b..efb1f4b2c69 100755
--- a/Master/bin/win32/tlmgr.bat
+++ b/Master/bin/win32/tlmgr.bat
@@ -1,27 +1,50 @@
@echo off
-rem Advanced starter for tlmgr with auto-update
+rem Advanced launcher for tlmgr with auto-update
+rem
rem Copyright 2009 by Tomasz M. Trzeciak <t.m.trzeciak@googlemail.com>
-rem Public Domain
+rem This file is licensed under the GNU General Public License version 2
+rem or any later version.
rem
-setlocal enableextensions
-rem TL installation root
-for %%P in ("%~dp0..\..") do set "tlroot=%%~fP"
+rem Check if we are running under NT based system
+rem (works for Vista too, extra check needed to exclude winNT4)
+if not [%OS%]==[Windows_NT] goto err_OS
+
+rem Make environment changes local & enable delayed expansion
+setlocal enabledelayedexpansion
+(set errorlevel=)
-rem not needed anymore
-rem path %TLdir%\tlpkg\installer;%path%
+rem Get TL installation root (it should be two levels up)
+for %%I in ("%~dp0..\..") do (set tlroot=%%~fI)
+
+rem Remove remains of previous update if any
+(set tlupdatername=run-updater-w32)
+(set tlupdater=%tlroot%\temp\%tlupdatername%)
+if exist "%tlupdater%*" del "%tlupdater%*"
+if exist "%tlupdater%*" goto :err_updater_exists
rem Start tlmgr
-set PERL5LIB=%tlroot%\tlpkg\tlperl\lib
+(set PERL5LIB=%tlroot%\tlpkg\tlperl\lib)
"%tlroot%\tlpkg\tlperl\bin\perl.exe" "%tlroot%\texmf\scripts\texlive\tlmgr.pl" %*
-rem Check for updater script
-set "updater=%tlroot%\temp\run-updater-w32"
-if not exist "%updater%" exit /b
-if exist "%updater%.bat" del "%updater%.bat"
-ren "%updater%" run-updater-w32.bat
-if errorlevel 1 exit /b 1
+rem Exit here if there are no updates to do
+if not exist "%tlupdater%" exit /b %errorlevel%
+rem Rename updater script before it is run
+ren "%tlupdater%" "%tlupdatername%.bat"
+if errorlevel 1 goto :err_rename_updater
+rem Run updater explicitly with cmd.exe, in case we are launched from 4NT
+rem Use delayed expansion for errorlevel, 4NT doesn't like: call exit /b %%errorlevel%%
+echo Starting update ...
+endlocal & call "%tlupdater%.bat" & exit /b !errorlevel!
+
+:err_updater_exists
+echo %~n0: cannot remove update script, infrastructure update might be in progress>&2
+exit /b 1
-rem Run updater script
-endlocal & call "%updater%.bat" & exit /b
+:err_rename_updater
+echo %~n0: cannot rename "%tlupdater%">&2
+exit /b 1
+:err_OS
+echo Unsupported operating system. Windows 2000 or later required.
+pause
diff --git a/Master/texmf/scripts/texlive/tlmgr.pl b/Master/texmf/scripts/texlive/tlmgr.pl
index 4c7253fe2c6..29ce78d57f8 100755
--- a/Master/texmf/scripts/texlive/tlmgr.pl
+++ b/Master/texmf/scripts/texlive/tlmgr.pl
@@ -35,11 +35,8 @@ BEGIN {
$^W = 1;
# make subprograms (including kpsewhich) have the right path:
$mydir = $0;
- $mydir =~ s!\\!/!g if $^O =~ /^MSWin(32|64)$/i;
$mydir =~ s,/[^/]*$,,;
- if ($^O=~/^MSWin(32|64)$/i) {
- $ENV{"PATH"} = "$mydir;$ENV{PATH}";
- } else {
+ if (!$^O=~/^MSWin(32|64)$/i) {
$ENV{"PATH"} = "$mydir:$ENV{PATH}";
}
#
@@ -1198,15 +1195,19 @@ sub write_w32_updater {
}
return 0 if ($opts{"dry-run"}); # nothing else to do
# write the updater script file
- open UPDATER, ">$root/temp/run-updater-w32"
- or die "Cannot create updater: $!";
- print UPDATER '@echo off
+ open UPDATER, ">$root/temp/run-updater-w32" or die "Cannot create updater: $!";
+ print UPDATER '
+@echo off
setlocal enableextensions
(set errorlevel=)
+(set guimode=' . $::gui_mode . ')
>nul copy /y "%~dp0..\texmf\scripts\texlive\updater-w32.bat" "%~dp0updater-w32.bat"
-call "%~dp0updater-w32" ' . join(' ',@updater_args) . '
-if errorlevel 1 call exit /b %%errorlevel%%
-start /b cmd /c del "%~f0" "%~dp0updater-w32.bat"';
+rem Execute with cmd.exe to avoid problems if 4NT is used
+rem Keep files write open during execution to signal running state
+cmd.exe /c call "%~dp0updater-w32.bat" ' . join(' ',@updater_args) . ' 8^>^>"%~f0" 9^>^>"%~dp0updater-w32.bat"
+rem Self-delete without error message about missing file
+(if not errorlevel 1 start /b cmd.exe /c del "%~f0" "%~dp0updater-w32.bat") & exit /b %errorlevel%
+';
close UPDATER;
return 0;
}
@@ -1714,7 +1715,7 @@ sub action_update {
tlwarn ("Aborting infrastructure update.\n") if ($ret);
}
- if (($nrupdated == 0) && ($tlmediasrc->media ne "NET") && $opts{"all"}) {
+ if (!(@new || @updated || @w32_updated) && ($tlmediasrc->media ne "NET") && $opts{"all"}) {
# for all but net updates we warn if nothing is updated
tlwarn("\nNothing to update.\n");
tlwarn("\nYour installation is set up to look on the disk for updates.\n");
diff --git a/Master/texmf/scripts/texlive/updater-w32.bat b/Master/texmf/scripts/texlive/updater-w32.bat
index 0482f1d2d84..2984c0564c2 100644
--- a/Master/texmf/scripts/texlive/updater-w32.bat
+++ b/Master/texmf/scripts/texlive/updater-w32.bat
@@ -7,118 +7,151 @@ rem This file is licensed under the GNU General Public License version 2
rem or any later version.
rem
-rem This script makes some very specific assumptions.
-rem Arguments are expected to be a package list passed in triples:
-rem package-name old-revision-number new-revision-number
-rem For each package-name a tar archive package-name.tar is
-rem expected as well (also for .source and .doc pseudo packages -
-rem - those are for distribution only and don't appear as separate
-rem entries in tlpdb) and a corresponding backup archive
-rem __BACKUP_package-name.rXXX.tar, where XXX is (old)
-rem revision number (.source and .doc are included in them)
-
-rem The update logic is follows:
-rem (1) untar all package archives
-rem (2) include .tlpobj files into tlpdb
-rem (3) print update info
-rem Any error during (1) or (2) trigers a rollback action:
-rem (1) print failed update info
-rem (2) untar all package backups
-rem (3) include .tlpobj files (from backup) into tlpdb
-rem (4) print restore info and popup an error dialog
-rem Any error during (1) or (2) and we go into panic mode.
-rem At this point there is no guarantee that the installation is still
-rem working. There is not much we can do but to print failed restore info
-rem and popup a fatal error dialog with instructions to download and run
-rem 'update-tlmgr-latest.exe' when everything else failed.
-
-rem make environment changes local & enable cmd extensions
-setlocal enableextensions
-rem get installation root
-for /f "delims=" %%D in ('kpsewhich -var-value=SELFAUTOPARENT') do (set tlroot=%%~fD)
-if exist "%tlroot%\" goto :foundtlroot
->&2 echo Could not locate installation root.
-exit /b 1
-
-:foundtlroot
-rem get location of the log file
-for /f "delims=" %%D in ('kpsewhich -var-value=TEXMFSYSVAR') do (set logdir=%%~fD\web2c)
-if not exist "%logdir%\" (set logdir=temp)
-rem cd to root
-cd /d "%tlroot%"
-rem create tar.exe backup
->nul copy /y tlpkg\installer\tar.exe temp\w32_tar.exe
-rem set up perl environment
-set "PERL5LIB=%tlroot%\tlpkg\tlperl\lib"
-rem let's make sure that we can use dynamic variables
+:: ===================================================================
+:: 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 .lzma 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 (1) or (2) 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 package list from arguments
+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 exit /b 0
-rem construct package list without .source and .doc packages
-rem count the total number of packages while doing that
+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%
+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 "temp\" %pkgpartslist% || goto :rollback
-call :foreachpkg :incltlpobj "tlpkg\tlpobj\" %pkgpartslist% || goto :rollback
-call :foreachpkg :update_info "" %pkglist%
-echo Update complete.
+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 :update_info ">&2" %pkglist%
->&2 echo Update failed! Rolling back to previous version...
-call :foreachpkg :untar "temp\__BACKUP_" %pkglist% || goto :panic
-call :foreachpkg :incltlpobj "tlpkg\tlpobj\" %pkglist% || goto :panic
-call :foreachpkg :restore_info "" %pkglist%
-echo Recovery from backup successful.
-call :errorpopup "ERROR: TeX Live" "TeX Live infrastructure update failed."
+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 :restore_info ">&2" %pkglist%
->&2 echo FATAL ERROR: recovery from backup failed!
-echo Your TeX Live installation may be broken, to repair it download and run:
-echo http://mirror.ctan.org/systems/texlive/tlnet/2008/update-tlmgr-latest.exe
-call :errorpopup "FATAL ERROR: TeX Live" "TeX Live infrastructure update failed and so did recovery from backup.\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"
+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
-2>nul del temp\w32_tar.exe temp\__BACKUP_*
+del "%tlroot%\temp\tar-w32.exe" "%tlroot%\temp\__BACKUP_*" >nul 2>&1
exit /b %exitcode%
REM SUBROUTINES
-:foreachpkg cmd prefix [pkg_name oldrev newrev [...]]
-set pkgcurr=0
+:foreachpkg cmd prefix pkgname oldrev newrev ...
+set pkgnr=0
:pkgloop
if [%3]==[] exit /b 0
-set /a pkgcurr+=1
-call %~1 %2 %3 %4 %5
-if errorlevel 1 exit /b %errorlevel%
+call :%1 %2 %3 %4 %5
+if errorlevel 1 exit /b 1
shift /3 & shift /3 & shift /3
goto :pkgloop
-:untar temp\[__BACKUP_] pkg_name
-set "ext=tar"
-if %~n1_==__BACKUP__ set "ext=r%~3.tar"
-temp\w32_tar.exe -x -f "%~1%~2.%ext%" && del "%~1%~2.%ext%"
-exit /b %errorlevel%
-
-:incltlpobj tlpkg\tlpobj\ pkg_name
-tlpkg\tlperl\bin\perl.exe texmf\scripts\texlive\tlmgr.pl _include_tlpobj "%~1%~2.tlpobj"
-exit /b %errorlevel%
-
:remove_src_doc
if /i %~x2.==.source. exit /b 0
if /i %~x2.==.doc. exit /b 0
@@ -126,19 +159,34 @@ set %1=%pkglist% %2 %3 %4
set /a pkgcount+=1
exit /b 0
-:update_info redir pkg_name oldrev newrev
-set "infomsg=update: %~2 (%~3 -^> %~4)"
-goto :continue_info
-:restore_info redir pkg_name oldrev newrev
-set "infomsg=restore: %~2 (%~3)"
-:continue_info
-if "%~1"==">&2" set "infomsg=failed %infomsg%"
->>"%logdir%\tlmgr.log" echo [%date% %time%] %infomsg%
-%~1 echo [%pkgcurr%/%pkgcount%] %infomsg%
+: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
-:errorpopup "title string" "message text"
->temp\errorpopup.vbs echo CreateObject("Scripting.FileSystemObject").DeleteFile(WScript.ScriptFullName) : MsgBox Replace("%~2","\n",Chr(10)), 16, "%~1"
-wscript temp\errorpopup.vbs
-rem del temp\errorpopup.vbs
+: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%