├── .gitignore ├── README.md ├── VERSION ├── bin ├── pecl.bat ├── pecl_build_all.bat ├── pecl_build_discord.bat ├── pecl_build_next.bat ├── pecl_rss.bat ├── pecl_rss_task.bat ├── pickle.bat ├── pickle_build_all.bat ├── pickle_build_next.bat ├── pickle_ctl.bat ├── pickleweb_sync_task.bat ├── rmtools_setvars.bat-dist ├── snap-x64.bat ├── snap.bat └── snapshot_task.bat ├── data ├── config.php ├── config │ ├── branch │ │ ├── x64 │ │ │ ├── php70.ini │ │ │ ├── php71.ini │ │ │ ├── php72.ini │ │ │ ├── php73.ini │ │ │ ├── php74.ini │ │ │ ├── php80.ini │ │ │ ├── php81.ini │ │ │ ├── php82.ini │ │ │ └── phpmaster.ini │ │ └── x86 │ │ │ ├── php70.ini │ │ │ ├── php71.ini │ │ │ ├── php72.ini │ │ │ ├── php73.ini │ │ │ ├── php74.ini │ │ │ ├── php80.ini │ │ │ ├── php81.ini │ │ │ ├── php82.ini │ │ │ └── phpmaster.ini │ ├── credentials_ftps.php-dist │ ├── pecl │ │ ├── cron │ │ │ ├── pecl_build_cleanup2.xml │ │ │ ├── pecl_build_next.xml │ │ │ └── pecl_rss_update.xml │ │ ├── exts.ini │ │ ├── libs.ini │ │ ├── pecl56_x64.ini │ │ ├── pecl56_x86.ini │ │ ├── pecl70_x64.ini │ │ ├── pecl70_x86.ini │ │ ├── pecl71_x64.ini │ │ ├── pecl71_x86.ini │ │ ├── pecl72_x64.ini │ │ ├── pecl72_x86.ini │ │ ├── pecl73_x64.ini │ │ ├── pecl73_x86.ini │ │ ├── pecl74_x64.ini │ │ ├── pecl74_x86.ini │ │ ├── pecl80_x64.ini │ │ ├── pecl80_x86.ini │ │ ├── pecl81_x64.ini │ │ ├── pecl81_x86.ini │ │ ├── pecl82_x64.ini │ │ └── pecl82_x86.ini │ ├── pickle │ │ ├── cron │ │ │ ├── pickle_build_next.xml │ │ │ └── pickleweb_sync.xml │ │ ├── exts.ini │ │ ├── libs.ini │ │ ├── pickle53.ini │ │ ├── pickle54.ini │ │ ├── pickle55.ini │ │ ├── pickle56.ini │ │ └── pickle70.ini │ └── repo │ │ └── phpnet.ini ├── db │ └── .dummy └── doc │ └── README.PECL.WIN ├── include ├── Branch.php ├── BranchConfig.php ├── Build.php ├── BuildVC.php ├── Git.php ├── MakeLogParser.php ├── MakeLogParserVC.php ├── PeclBranch.php ├── PeclBuildVC.php ├── PeclDb.php ├── PeclExt.php ├── PeclMail.php ├── Pickle.php ├── PickleBranch.php ├── PickleBuildVC.php ├── PickleDb.php ├── PickleExt.php ├── PickleJob.php ├── PickleWeb.php ├── Repository.php ├── Svn.php └── Tools.php ├── locks └── .dummy ├── logs └── .dummy ├── script ├── pecl.php ├── pecl_rss.php ├── pickle.php ├── pickle_ctl.php └── snap.php ├── template ├── log_style.css ├── mail_notification.tpl.php └── make_log.tpl.php └── tmp └── .dummy /.gitignore: -------------------------------------------------------------------------------- 1 | credentials_ftps.php 2 | data/db/*.json 3 | logs/*.log 4 | locks/*.lock 5 | bin/rmtools_setvars.bat 6 | tmp/*.zip 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PHP RMTOOLS 2 | 3 | Tools PHP release and snapshot build automation for Windows. 4 | 5 | Since this software is no longer used for build automation on Windows, 6 | it has been archived. 7 | 8 | # License 9 | 10 | The PHP RMTOOLS itself is licensed under the BSD 2-Clause license. With the usage of the other tools, you accept the respective licenses. 11 | 12 | # Overview 13 | 14 | 15 | 16 | # Requirements 17 | 18 | - Visual Studio 19 | - [PHP-SDK](https://github.com/OSTC/php-sdk-binary-tools) 20 | 21 | 22 | # Usage 23 | 24 | NOTE: All the paths in the usage exampled are on drive C: for simplicity. Locations of PHP SDK and RMTOOLS are customizable and are not bound to a firm path on the system. All the path configuration is editable in the corresponding branch ini files under `rmtools\data\config\branch` 25 | 26 | 27 | ## Preparing 28 | 29 | 30 | - install [Git](https://git-scm.com/), alternatively - fetch the latest tags for RMTOOLS and PHP SDK 31 | - `md c:\php-snap-build` 32 | - `cd c:\php-snap-build` 33 | - `git clone https://github.com/Microsoft/php-sdk-binary-tools.git php-sdk` 34 | - `git clone https://github.com/php/web-rmtools.git rmtools` 35 | - `md c:\php-snap-build\obj-x64`, or alternatively similar to `mklink /d obj-x64 d:\tmp-obj-x64` 36 | - `md c:\php-snap-build\obj`, or alternatively similar to `mklink /d obj d:\tmp-obj` 37 | - `md C:\php-snap-build\snap_master\vc14\x64` 38 | - `md C:\php-snap-build\snap_master\vc14\x86` 39 | - copy C:\php-snap-build\rmtools\bin\rmtools_setvars.bat-dist to C:\php-snap-build\rmtools\bin\rmtools_setvars.bat, set the appropriate values 40 | - copy C:\php-snap-build\rmtools\data\config\credentials_ftps.php-dist to C:\php-snap-build\rmtools\data\config\credentials_ftps.php, set the appropriate values 41 | 42 | ## Building 43 | 44 | With this configuration, for example for a VC14 64-bit build 45 | 46 | - the build dir is C:\php-snap-build\snap_master\vc14\x64 47 | - the object dir is C:\php-snap-build\obj-x64 48 | - the package dir is C:\php-snap-build\obj-x64 49 | - run `c:\php-snap-build\php-sdk\phpsdk-vc14-x64.bat -t c:\php-snap-build\rmtools\bin\snapshot_task.bat --task-args " "` 50 | 51 | `` is the name of one of the INI files in data\config\branch (e.g. `phpmaster`), 52 | and `` is the name of one of the sections in that INI file (e.g. `nts-windows-vc15-x64`). 53 | `` can also be `all`, to build all types defined in the given INI file. 54 | 55 | To make a x86 build, the corresponding starter script from the PHP SDK needs to be used. 56 | 57 | 58 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 2.0.0-dev 2 | -------------------------------------------------------------------------------- /bin/pecl.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | rem must be on the env already 4 | if "%PHP_SDK_ROOT_PATH%"=="" ( 5 | echo PHP SDK is not setup 6 | exit /b 3 7 | ) 8 | call %~dp0rmtools_setvars.bat 9 | 10 | if "%1"=="" goto :help 11 | if "%1"=="--help" goto :help 12 | if "%1"=="-h" goto :help 13 | if "%1"=="/?" goto :help 14 | goto :skip_help 15 | 16 | :help 17 | %PHP_SDK_PHP_CMD% %PHP_RMTOOLS_SCRIPT_PATH%\pecl.php 18 | GOTO EXIT_LOCKED 19 | 20 | :skip_help 21 | 22 | if not exist "%PHP_RMTOOLS_ROOT_PATH%\data\config\credentials_ftps.php" ( 23 | echo FTP config %PHP_SDK_ROOT_PATH%\data\config\credentials_ftps.php not found 24 | exit /b 3 25 | ) 26 | 27 | REM Run pecl.php 28 | @ECHO ON 29 | %PHP_SDK_PHP_CMD% %PHP_RMTOOLS_SCRIPT_PATH%\pecl.php %* 30 | @ECHO OFF 31 | 32 | :EXIT_LOCKED 33 | echo . 34 | 35 | -------------------------------------------------------------------------------- /bin/pecl_build_all.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | if not exist %~dp0rmtools_setvars.bat ( 4 | echo RMTOOLS is not setup, create %~dp0rmtools_setvars.bat 5 | exit /b 3 6 | ) 7 | call %~dp0rmtools_setvars.bat 8 | 9 | for /f "tokens=1-8 delims=-" %%a in ('powershell get-date -format "{yyyy-MM-dd-HH-mm-ss-ff}"') do set cur_date=%%a-%%b-%%c_%%d-%%e-%%f.%%g 10 | 11 | set LOG_FILE=%PHP_RMTOOLS_LOG_PATH%\task-pecl-%cur_date%.log 12 | set LOCK_FILE=%PHP_RMTOOLS_LOCK_PATH%\pecl.lock 13 | 14 | if "%1"=="" goto :help 15 | if "%1"=="--help" goto :help 16 | if "%1"=="-h" goto :help 17 | if "%1"=="/?" goto :help 18 | goto :skip_help 19 | 20 | :help 21 | echo ========================================================== 22 | echo This is the PECL build batch script. You can see the help 23 | echo output of the underlaying worker below. Note that you HAVE 24 | echo TO ommit the --config option when running this batch. 25 | echo ========================================================== 26 | call "%PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\phpsdk-starter.bat" -c vc14 -a x64 -t "%PHP_RMTOOLS_BIN_PATH%\pecl.bat" 27 | echo . 28 | exit /b 0 29 | 30 | :skip_help 31 | 32 | IF EXIST "%LOCK_FILE%" ( 33 | ECHO Pecl build script is already running. 34 | echo . 35 | exit /b 3 36 | ) 37 | 38 | ECHO running > "%LOCK_FILE%" 39 | 40 | rem Notice the --first and the --last calls marked, that's important 41 | rem to maintain the state between call for the same package. For instance 42 | rem if --aggregate-mail is used. 43 | call "%PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\phpsdk-starter.bat" -c vs16 -a x64 -t "%PHP_RMTOOLS_BIN_PATH%\pecl.bat" --task-args "--config=pecl81_x64 --first %*" >> "%LOG_FILE%" 2<&1 44 | call "%PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\phpsdk-starter.bat" -c vs16 -a x86 -t "%PHP_RMTOOLS_BIN_PATH%\pecl.bat" --task-args "--config=pecl81_x86 %*" >> "%LOG_FILE%" 2<&1 45 | call "%PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\phpsdk-starter.bat" -c vs16 -a x64 -t "%PHP_RMTOOLS_BIN_PATH%\pecl.bat" --task-args "--config=pecl80_x64 %*" >> "%LOG_FILE%" 2<&1 46 | call "%PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\phpsdk-starter.bat" -c vs16 -a x86 -t "%PHP_RMTOOLS_BIN_PATH%\pecl.bat" --task-args "--config=pecl80_x86 %*" >> "%LOG_FILE%" 2<&1 47 | call "%PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\phpsdk-starter.bat" -c vc15 -a x64 -t "%PHP_RMTOOLS_BIN_PATH%\pecl.bat" --task-args "--config=pecl74_x64 %*" >> "%LOG_FILE%" 2<&1 48 | call "%PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\phpsdk-starter.bat" -c vc15 -a x86 -t "%PHP_RMTOOLS_BIN_PATH%\pecl.bat" --task-args "--config=pecl74_x86 --last %*" >> "%LOG_FILE%" 2<&1 49 | 50 | echo Done.>> "%LOG_FILE%" 51 | 52 | del "%LOCK_FILE%" >> "%LOG_FILE%" 2<&1 53 | 54 | echo . 55 | exit /b 0 56 | 57 | -------------------------------------------------------------------------------- /bin/pecl_build_discord.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | if not exist %~dp0rmtools_setvars.bat ( 4 | echo RMTOOLS is not setup, create %~dp0rmtools_setvars.bat 5 | exit /b 3 6 | ) 7 | call %~dp0rmtools_setvars.bat 8 | 9 | for /f "tokens=1-8 delims=-" %%a in ('powershell get-date -format "{yyyy-MM-dd-HH-mm-ss-ff}"') do set cur_date=%%a-%%b-%%c_%%d-%%e-%%f.%%g 10 | 11 | set LOG_FILE=%PHP_RMTOOLS_LOG_PATH%\task-pecl-pre-%cur_date%.log 12 | set LOCK_FILE=%PHP_RMTOOLS_LOCK_PATH%\pecl.lock 13 | 14 | if "%1"=="" goto :help 15 | if "%1"=="--help" goto :help 16 | if "%1"=="-h" goto :help 17 | if "%1"=="/?" goto :help 18 | goto :skip_help 19 | 20 | :help 21 | echo ========================================================== 22 | echo This is the PECL build batch script. You can see the help 23 | echo output of the underlaying worker below. Note that you HAVE 24 | echo TO ommit the --config option when running this batch. 25 | echo ========================================================== 26 | call "%PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\phpsdk-starter.bat" -c vs16 -a x64 -t "%PHP_RMTOOLS_BIN_PATH%\pecl.bat" 27 | GOTO EXIT_LOCKED 28 | 29 | :skip_help 30 | 31 | IF EXIST "%LOCK_FILE%" ( 32 | ECHO Pecl build script is already running. 33 | GOTO EXIT_LOCKED 34 | ) 35 | 36 | ECHO running > "%LOCK_FILE%" 37 | 38 | rem Notice the --first and the --last calls marked, that's important 39 | rem to maintain the state between call for the same package. For instance 40 | rem if --aggregate-mail is used. 41 | rem call %BAT_DIR%pecl.bat --config=pecl55_x64 --first %* >> %LOG_FILE% 2<&1 42 | rem call %BAT_DIR%pecl.bat --config=pecl55_x86 %* >> %LOG_FILE% 2<&1 43 | rem call %BAT_DIR%pecl.bat --config=pecl54 %* >> %LOG_FILE% 2<&1 44 | rem call %BAT_DIR%pecl.bat --config=pecl53 --last %* >> %LOG_FILE% 2<&1 45 | rem 46 | call "%PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\phpsdk-starter.bat" -c vs16 -a x64 -t "%PHP_RMTOOLS_BIN_PATH%\pecl.bat" --task-args "--config=pecl82_x64 --first %*" >> "%LOG_FILE%" 2<&1 47 | call "%PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\phpsdk-starter.bat" -c vs16 -a x86 -t "%PHP_RMTOOLS_BIN_PATH%\pecl.bat" --task-args "--config=pecl82_x86 --last %*" >> "%LOG_FILE%" 2<&1 48 | 49 | echo Done.>> "%LOG_FILE%" 50 | 51 | del "%LOCK_FILE%" >> "%LOG_FILE%" 2<&1 52 | 53 | :EXIT_LOCKED 54 | echo . 55 | 56 | -------------------------------------------------------------------------------- /bin/pecl_build_next.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | rem pick the next PECL pkg and pass to pecl_build_all.bat 4 | rem first try releases, if there aren't any, look for snaps 5 | 6 | if not exist %~dp0rmtools_setvars.bat ( 7 | echo RMTOOLS is not setup, create %~dp0rmtools_setvars.bat 8 | exit /b 3 9 | ) 10 | call %~dp0rmtools_setvars.bat 11 | 12 | if not exist %PHP_RMTOOLS_PECL_IN_PKG_PATH% ( 13 | echo %PHP_RMTOOLS_PECL_IN_PKG_PATH% does not exist 14 | exit /b 3 15 | ) 16 | pushd %PHP_RMTOOLS_PECL_IN_PKG_PATH% 17 | 18 | for /r %%i in (*) do ( 19 | call "%PHP_RMTOOLS_BIN_PATH%\pecl_build_all.bat" --upload --aggregate-mail --package=%%i 20 | del %%i 21 | goto ONLY_ONE 22 | ) 23 | popd 24 | 25 | if not exist %PHP_RMTOOLS_PECL_IN_PKG_NOMAIL_PATH% ( 26 | echo %PHP_RMTOOLS_PECL_IN_PKG_NOMAIL_PATH% does not exist 27 | exit /b 3 28 | ) 29 | pushd %PHP_RMTOOLS_PECL_IN_PKG_NOMAIL_PATH% 30 | 31 | for /r %%i in (*) do ( 32 | call "%PHP_RMTOOLS_BIN_PATH%\pecl_build_all.bat" --upload --package=%%i 33 | del %%i 34 | goto ONLY_ONE 35 | ) 36 | popd 37 | 38 | if not exist %PHP_RMTOOLS_PECL_IN_SNAP_PATH% ( 39 | echo %PHP_RMTOOLS_PECL_IN_SNAP_PATH% does not exist 40 | exit /b 3 41 | ) 42 | pushd %PHP_RMTOOLS_PECL_IN_SNAP_PATH% 43 | 44 | for /r %%i in (*) do ( 45 | call "%PHP_RMTOOLS_BIN_PATH%\pecl_build_all.bat" --upload --is-snap --aggregate-mail --package=%%i 46 | del %%i 47 | goto ONLY_ONE 48 | ) 49 | popd 50 | 51 | if not exist %PHP_RMTOOLS_PECL_IN_SNAP_NOMAIL_PATH% ( 52 | echo %PHP_RMTOOLS_PECL_IN_SNAP_NOMAIL_PATH% does not exist 53 | exit /b 3 54 | ) 55 | pushd %PHP_RMTOOLS_PECL_IN_SNAP_NOMAIL_PATH% 56 | 57 | for /r %%i in (*) do ( 58 | call "%PHP_RMTOOLS_BIN_PATH%\pecl_build_all.bat" --upload --is-snap --package=%%i 59 | del %%i 60 | goto ONLY_ONE 61 | ) 62 | popd 63 | 64 | if not exist %PHP_RMTOOLS_PECL_IN_SNAP_PRE_PATH% ( 65 | echo %PHP_RMTOOLS_PECL_IN_SNAP_PRE_PATH% does not exist 66 | exit /b 3 67 | ) 68 | pushd %PHP_RMTOOLS_PECL_IN_SNAP_PRE_PATH% 69 | 70 | for /r %%i in (*) do ( 71 | call "%PHP_RMTOOLS_BIN_PATH%\pecl_build_discord.bat" --upload --is-snap --aggregate-mail --package=%%i 72 | del %%i 73 | goto ONLY_ONE 74 | ) 75 | popd 76 | 77 | if not exist %PHP_RMTOOLS_PECL_IN_SNAP_NOMAIL_PRE_PATH% ( 78 | echo %PHP_RMTOOLS_PECL_IN_SNAP_NOMAIL_PRE_PATH% does not exist 79 | exit /b 3 80 | ) 81 | pushd %PHP_RMTOOLS_PECL_IN_SNAP_NOMAIL_PRE_PATH% 82 | 83 | for /r %%i in (*) do ( 84 | call "%PHP_RMTOOLS_BIN_PATH%\pecl_build_discord.bat" --upload --is-snap --package=%%i 85 | del %%i 86 | goto ONLY_ONE 87 | ) 88 | popd 89 | 90 | if not exist %PHP_RMTOOLS_PECL_IN_PKG_MASS_REBUILD_PATH% ( 91 | echo %PHP_RMTOOLS_PECL_IN_PKG_MASS_REBUILD_PATH% does not exist 92 | exit /b 3 93 | ) 94 | pushd %PHP_RMTOOLS_PECL_IN_PKG_MASS_REBUILD_PATH% 95 | 96 | for /r %%i in (*) do ( 97 | call "%PHP_RMTOOLS_BIN_PATH%\pecl_build_discord.bat" --upload --aggregate-mail --package=%%i 98 | del %%i 99 | goto ONLY_ONE 100 | ) 101 | popd 102 | 103 | if not exist %PHP_RMTOOLS_PECL_IN_PKG_MASS_REBUILD_NOMAIL_PATH% ( 104 | echo %PHP_RMTOOLS_PECL_IN_PKG_MASS_REBUILD_NOMAIL_PATH% does not exist 105 | exit /b 3 106 | ) 107 | pushd %PHP_RMTOOLS_PECL_IN_PKG_MASS_REBUILD_NOMAIL_PATH% 108 | 109 | for /r %%i in (*) do ( 110 | call "%PHP_RMTOOLS_BIN_PATH%\pecl_build_discord.bat" --upload --package=%%i 111 | del %%i 112 | goto ONLY_ONE 113 | ) 114 | popd 115 | 116 | :ONLY_ONE 117 | popd 118 | echo . 119 | 120 | -------------------------------------------------------------------------------- /bin/pecl_rss.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | call %~dp0rmtools_setvars.bat 4 | 5 | set PHP_DIR=%PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\bin\php 6 | set PECL_RSS_CMD=%PHP_DiR%\php.exe -c %PHP_DIR%\php.ini -d extension_dir=%PHP_DIR%\ext 7 | 8 | if "%1"=="" goto :help 9 | if "%1"=="--help" goto :help 10 | if "%1"=="-h" goto :help 11 | if "%1"=="/?" goto :help 12 | goto :skip_help 13 | 14 | :help 15 | %PECL_RSS_CMD% %PHP_RMTOOLS_SCRIPT_PATH%\pecl_rss.php 16 | GOTO EXIT_LOCKED 17 | 18 | :skip_help 19 | 20 | 21 | %PECL_RSS_CMD% %PHP_RMTOOLS_SCRIPT_PATH%\pecl_rss.php %* 22 | 23 | :EXIT_LOCKED 24 | echo . 25 | 26 | -------------------------------------------------------------------------------- /bin/pecl_rss_task.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | call %~dp0rmtools_setvars.bat 4 | 5 | set LOG_FILE=%PHP_RMTOOLS_LOG_PATH%\task-pecl-rss.log 6 | 7 | 8 | if "%1"=="" goto :help 9 | if "%1"=="--help" goto :help 10 | if "%1"=="-h" goto :help 11 | if "%1"=="/?" goto :help 12 | goto :skip_help 13 | 14 | :help 15 | echo ========================================================== 16 | echo This is the PECL RSS task script. You can see the help 17 | echo output of the underlaying worker below. This script will 18 | echo fetch the items from the current RSS feed, download and 19 | echo put them into the build queue. 20 | echo ========================================================== 21 | call %PHP_RMTOOLS_BIN_PATH%\pecl_rss.bat 22 | GOTO EXIT_LOCKED 23 | 24 | :skip_help 25 | 26 | IF EXIST %PHP_RMTOOLS_LOCK_PATH%\pecl-rss.lock ( 27 | ECHO Pecl build script is already running. 28 | GOTO EXIT_LOCKED 29 | ) 30 | 31 | ECHO running > %PHP_RMTOOLS_LOCK_PATH%\pecl-rss.lock 32 | 33 | 34 | call %PHP_RMTOOLS_BIN_PATH%\pecl_rss.bat %* >> %LOG_FILE% 2<&1 35 | 36 | echo Done.>> %LOG_FILE% 37 | 38 | del %PHP_RMTOOLS_LOCK_PATH%\pecl-rss.lock >> %LOG_FILE% 2<&1 39 | 40 | :EXIT_LOCKED 41 | echo . 42 | 43 | -------------------------------------------------------------------------------- /bin/pickle.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | SET BAT_DIR=%~dp0 4 | 5 | set RMTOOLS_BASE_DIR=c:\php-sdk\rmtools-client 6 | 7 | set PECL_PHP_CMD=c:\php-sdk\php\php.exe -d memory_limit=2G 8 | 9 | if "%1"=="" goto :help 10 | if "%1"=="--help" goto :help 11 | if "%1"=="-h" goto :help 12 | if "%1"=="/?" goto :help 13 | goto :skip_help 14 | 15 | :help 16 | %PECL_PHP_CMD% %BAT_DIR%\..\script\pickle.php 17 | GOTO EXIT_LOCKED 18 | 19 | :skip_help 20 | 21 | CALL c:\php-sdk\bin\phpsdk_setvars.bat 22 | 23 | copy c:\php-sdk\rmtools.base\data\config\credentials_ftps.php %RMTOOLS_BASE_DIR%\data\config\ 24 | 25 | REM VC9 Support 26 | SET PSDK_61_DIR=C:\Program Files\Microsoft SDKs\Windows\v6.1 27 | SET VC9_DIR=C:\Program Files (x86)\Microsoft Visual Studio 9.0 28 | SET VC9_SHELL=C:\WINDOWS\system32\cmd.exe /E:ON /V:ON /T:0E /K "C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin\SetEnv.Cmd" 29 | SET VC9_INCLUDE=%PSDK_61_DIR%\include;%VC9_DIR%\VC\ATLMFC\INCLUDE;%VC9_DIR%\VC\INCLUDE 30 | SET VC9_LIB=%PSDK_61_DIR%\lib;%VC9_DIR%\VC\ATLMFC\LIB;%VC9_DIR%\VC\LIB 31 | SET VC9_PATH=%VC9_DIR%\Common7\IDE;%VC9_DIR%\VC\BIN;%VC9_DIR%\Common7\Tools;%VC9_DIR%\VC\VCPackages;%PSDK_61_DIR%\bin;C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem 32 | SET VC9_X64_INCLUDE=%VC9_DIR%\VC\Include;C:\Program Files\Microsoft SDKs\Windows\v6.1\Include;C:\Program Files\Microsoft SDKs\Windows\v6.1\Include\gl;%VC9_DIR%VC\ATLMFC\INCLUDE; 33 | SET VC9_X64_LIB=%VC9_DIR%\VC\Lib\amd64;C:\Program Files\Microsoft SDKs\Windows\v6.1\Lib\x64;%VC9_DIR%\VC\ATLMFC\LIB\AMD64; 34 | SET VC9_X64_PATH=%VC9_DIR%\VC\Bin\x86_amd64;%VC9_DIR%\VC\Bin;%VC9_DIR%\VC\vcpackages;%VC9_DIR%\Common7\IDE;C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin;C:\WINDOWS\Microsoft.NET\Framework64\v3.5;C:\WINDOWS\Microsoft.NET\Framework\v3.5;C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727;C:\Perl\site\bin;C:\Perl\bin;C:\Program Files\PHP\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;c:\win2k3cd;C:\Program Files\cvsnt;C:\Program Files\WinSCP\;C:\Program Files\CVSNT\ 35 | SET OLD_PATH=%PATH% 36 | SET PATH=%PATH%;%VC9_PATH% 37 | SET LIB=%VC9_LIB% 38 | SET INCLUDE=%VC9_INCLUDE% 39 | 40 | REM VC11 Support 41 | SET VC11_SHELL=%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"" x86 42 | SET PSDK_80_DIR=C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0 43 | 44 | SET VC11_DIR=C:\Program Files (x86)\Microsoft Visual Studio 11.0 45 | SET VC11_INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\ATLMFC\INCLUDE;C:\Program Files (x86)\Windows Kits\8.0\include\shared;C:\Program Files (x86)\Windows Kits\8.0\include\um;C:\Program Files (x86)\Windows Kits\8.0\include\winrt; 46 | SET VC11_LIB=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\LIB;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\ATLMFC\LIB;C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86; 47 | SET LIBPATH=C:\Windows\Microsoft.NET\Framework\v4.0.30319;C:\Windows\Microsoft.NET\Framework\v3.5;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\LIB;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\ATLMFC\LIB;C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral;C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0\ExtensionSDKs\Microsoft.VCLibs\11.0\References\CommonConfiguration\neutral; 48 | SET INCLUDE=%VC11_INCLUDE% 49 | SET LIB=%VC11_LIB% 50 | 51 | SET VCINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\ 52 | SET VisualStudioVersion=11.0 53 | SET VS110COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools\ 54 | SET VSINSTALLDIR=C:\Program Files (x86)\Microsoft Visual Studio 11.0\ 55 | SET DevEnvDir=C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\ 56 | SET ExtensionSdkDir=C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0\ExtensionSDKs 57 | SET WindowsSdkDir=C:\Program Files (x86)\Windows Kits\8.0\ 58 | SET WindowsSdkDir_35=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\ 59 | SET WindowsSdkDir_old=C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\ 60 | 61 | SET VC11_PATH=C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow;C:\Program Files (x86)\Microsoft SDKs\F#\3.0\Framework\v4.0\;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VSTSDB\Deploy;C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\BIN;C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools;C:\Windows\Microsoft.NET\Framework\v4.0.30319;C:\Windows\Microsoft.NET\Framework\v3.5;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\VCPackages;C:\Program Files (x86)\HTML Help Workshop;C:\Program Files (x86)\Microsoft Visual Studio 11.0\Team Tools\Performance Tools;C:\Program Files (x86)\Windows Kits\8.0\bin\x86;C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET WebPages\v1.0\;C:\Program Files\Microsoft SQL Server\110\Tools\Binn\;C:\Program Files (x86)\Windows Kits\8.0\Windows Performance Toolkit\ 62 | SET OLD_PATH=%PATH% 63 | SET PATH=%PATH%;%VC11_PATH% 64 | 65 | SET VC11_X64_PATH=C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\BIN\amd64;C:\Windows\Microsoft.NET\Framework64\v4.0.30319;C:\Windows\Microsoft.NET\Framework64\v3.5;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\VCPackages;C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE;C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\Tools;C:\Program Files (x86)\HTML Help Workshop;C:\Program Files (x86)\Microsoft Visual Studio 11.0\Team Tools\Performance Tools\x64;C:\Program Files (x86)\Microsoft Visual Studio 11.0\Team Tools\Performance Tools;C:\Program Files (x86)\Windows Kits\8.0\bin\x64;C:\Program Files (x86)\Windows Kits\8.0\bin\x86;C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\x64;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\x64;C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX4.0 Tools;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Microsoft\Web Platform Installer\;C:\Program Files (x86)\Microsoft ASP.NET\ASP.NET Web Pages\v1.0\;C:\Program Files\Microsoft SQL Server\110\Tools\Binn\;C:\Program Files (x86)\Windows Kits\8.0\Windows Performance Toolkit\ 66 | SET VC11_X64_INCLUDE=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\INCLUDE;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\ATLMFC\INCLUDE;C:\Program Files (x86)\Windows Kits\8.0\include\shared;C:\Program Files (x86)\Windows Kits\8.0\include\um;C:\Program Files (x86)\Windows Kits\8.0\include\winrt; 67 | SET VC11_X64_LIB=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\LIB\amd64;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\ATLMFC\LIB\amd64;C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x64; 68 | SET VC11_X64_LIBPATH=C:\Windows\Microsoft.NET\Framework64\v4.0.30319;C:\Windows\Microsoft.NET\Framework64\v3.5;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\LIB\amd64;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\ATLMFC\LIB\amd64;C:\Program Files (x86)\Windows Kits\8.0\References\CommonConfiguration\Neutral;C:\Program Files (x86)\Microsoft SDKs\Windows\v8.0\ExtensionSDKs\Microsoft.VCLibs\11.0\References\CommonConfiguration\neutral; 69 | SET VC11_X64_SHELL=%comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"" amd64 70 | 71 | REM Run pecl.php 72 | SET BISON_SIMPLE=c:\php-sdk\bin\bison.simple 73 | rem appending the git path to the end, this should reduce negative effects of command names clashing, fe "find". Pickle embedded within the other PHP scripts seems not be able to pickup the correct git.exe with proc_open(). For the last solution one can try installing msysgit globally on the system with the current installer, that will put git.exe on the path globally. 74 | set PATH=%PATH%;c:\\apps\\git\\bin 75 | @ECHO ON 76 | %PECL_PHP_CMD% %BAT_DIR%..\script\pickle.php %* 77 | @ECHO OFF 78 | SET PATH=%OLD_PATH% 79 | 80 | :EXIT_LOCKED 81 | echo . 82 | 83 | -------------------------------------------------------------------------------- /bin/pickle_build_all.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | SET BAT_DIR=%~dp0 4 | 5 | set yyyy=%date:~6,4% 6 | set mm=%date:~3,2% 7 | set dd=%date:~0,2% 8 | 9 | set hh=%time:~0,2% 10 | if %hh% lss 10 (set hh=0%time:~1,1%) 11 | set nn=%time:~3,2% 12 | set ss=%time:~6,2% 13 | set cur_date=%yyyy%%mm%%dd%-%hh%%nn%%ss% 14 | 15 | set LOG_FILE=c:\php-sdk\logs\task-pickle-%cur_date%.log 16 | set RMTOOLS_BASE_DIR=c:\php-sdk\rmtools-client 17 | 18 | if "%1"=="" goto :help 19 | if "%1"=="--help" goto :help 20 | if "%1"=="-h" goto :help 21 | if "%1"=="/?" goto :help 22 | goto :skip_help 23 | 24 | :help 25 | echo ========================================================== 26 | echo This is the pickle build batch script. You can see the help 27 | echo output of the underlaying worker below. Note that you HAVE 28 | echo TO ommit the --config option when running this batch. 29 | echo ========================================================== 30 | %BAT_DIR%pickle.bat 31 | GOTO EXIT_LOCKED 32 | 33 | :skip_help 34 | 35 | IF EXIST c:\php-sdk\locks\pickle.lock ( 36 | ECHO pickle build script is already running. 37 | GOTO EXIT_LOCKED 38 | ) 39 | 40 | ECHO running > c:\php-sdk\locks\pickle.lock 41 | 42 | rem Notice the --first and the --last calls marked, that's important 43 | rem to maintain the state between call for the same package. For instance 44 | rem if --aggregate-mail is used. 45 | call %BAT_DIR%pickle.bat --config=pickle70 --first %* >> %LOG_FILE% 2<&1 46 | call %BAT_DIR%pickle.bat --config=pickle56 %* >> %LOG_FILE% 2<&1 47 | call %BAT_DIR%pickle.bat --config=pickle55 %* >> %LOG_FILE% 2<&1 48 | call %BAT_DIR%pickle.bat --config=pickle54 %* >> %LOG_FILE% 2<&1 49 | call %BAT_DIR%pickle.bat --config=pickle53 --last %* >> %LOG_FILE% 2<&1 50 | 51 | echo Done.>> %LOG_FILE% 52 | 53 | del c:\php-sdk\locks\pickle.lock >> %LOG_FILE% 2<&1 54 | 55 | :EXIT_LOCKED 56 | echo . 57 | 58 | -------------------------------------------------------------------------------- /bin/pickle_build_next.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | rem pick the next pickle pkg and pass to pickle_build_all.bat 4 | rem first try releases, if there aren't any, look for snaps 5 | 6 | rem in contrary to pecl, the pickle build bot doesn't download 7 | rem the releases itself, but get the job files created by the 8 | rem peclweb job script 9 | 10 | SET BAT_DIR=%~dp0 11 | 12 | 13 | rem jobs first, sourceballs then (will be rare supposedly); 14 | rem btw aggregate mail and co isn't implemented, just left as it'll maybe need to be 15 | 16 | cd c:\pickle-in-job 17 | 18 | for /r %%i in (*) do ( 19 | call %BAT_DIR%pickle_build_all.bat --upload --aggregate-mail --job=%%i 20 | del %%i 21 | goto ONLY_ONE 22 | ) 23 | 24 | 25 | cd c:\pickle-in-snap-job 26 | 27 | for /r %%i in (*) do ( 28 | call %BAT_DIR%pickle_build_all.bat --upload --is-snap --aggregate-mail --job=%%i 29 | del %%i 30 | goto ONLY_ONE 31 | ) 32 | 33 | 34 | cd c:\pickle-in-pkg 35 | 36 | for /r %%i in (*) do ( 37 | call %BAT_DIR%pickle_build_all.bat --upload --aggregate-mail --package=%%i 38 | del %%i 39 | goto ONLY_ONE 40 | ) 41 | 42 | rem cd c:\pickle-in-pkg-nomail 43 | 44 | rem for /r %%i in (*) do ( 45 | rem call %BAT_DIR%pickle_build_all.bat --upload --package=%%i 46 | rem del %%i 47 | rem goto ONLY_ONE 48 | rem ) 49 | 50 | cd c:\pickle-in-snap 51 | 52 | for /r %%i in (*) do ( 53 | call %BAT_DIR%pickle_build_all.bat --upload --is-snap --aggregate-mail --package=%%i 54 | del %%i 55 | goto ONLY_ONE 56 | ) 57 | 58 | rem cd c:\pickle-in-snap-nomail 59 | 60 | rem for /r %%i in (*) do ( 61 | rem call %BAT_DIR%pickle_build_all.bat --upload --is-snap --package=%%i 62 | rem del %%i 63 | rem goto ONLY_ONE 64 | rem ) 65 | 66 | :ONLY_ONE 67 | cd %BAT_DIR% 68 | echo . 69 | 70 | -------------------------------------------------------------------------------- /bin/pickle_ctl.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | SET BAT_DIR=%~dp0 4 | 5 | set PECL_RSS_CMD=c:\php-sdk\php\php.exe 6 | 7 | if "%1"=="" goto :help 8 | if "%1"=="--help" goto :help 9 | if "%1"=="-h" goto :help 10 | if "%1"=="/?" goto :help 11 | goto :skip_help 12 | 13 | :help 14 | %PECL_RSS_CMD% %BAT_DIR%\..\script\pickle_ctl.php 15 | GOTO EXIT_LOCKED 16 | 17 | :skip_help 18 | 19 | 20 | %PECL_RSS_CMD% %BAT_DIR%\..\script\pickle_ctl.php %* 21 | 22 | :EXIT_LOCKED 23 | echo . 24 | 25 | -------------------------------------------------------------------------------- /bin/pickleweb_sync_task.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | SET BAT_DIR=%~dp0 4 | 5 | set LOG_FILE=c:\php-sdk\logs\task-pickleweb-sync.log 6 | 7 | set PECL_RSS_CMD=c:\php-sdk\php\php.exe -d extension_dir=c:\php-sdk\php\ext -d extension=php_openssl.dll -d extension=php_curl.dll -d extension=php_sqlite3.dll -d date.timezone=UTC %BAT_DIR%\..\script\pickleweb_ctl.php %* >> %LOG_FILE% 2<&1 8 | 9 | 10 | if "%1"=="" goto :help 11 | if "%1"=="--help" goto :help 12 | if "%1"=="-h" goto :help 13 | if "%1"=="/?" goto :help 14 | goto :skip_help 15 | 16 | :help 17 | echo ========================================================== 18 | echo This is the PECL RSS task script. You can see the help 19 | echo output of the underlaying worker below. This script will 20 | echo fetch the items from the current RSS feed, download and 21 | echo put them into the build queue. 22 | echo ========================================================== 23 | call %BAT_DIR%pickle_ctl.bat 24 | GOTO EXIT_LOCKED 25 | 26 | :skip_help 27 | 28 | IF EXIST c:\php-sdk\locks\pickleweb-sync.lock ( 29 | ECHO Pickleweb sync is already running. 30 | GOTO EXIT_LOCKED 31 | ) 32 | 33 | ECHO running > c:\php-sdk\locks\pickleweb-sync.lock 34 | 35 | 36 | call %BAT_DIR%pickle_ctl.bat %* >> %LOG_FILE% 2<&1 37 | 38 | echo Done.>> %LOG_FILE% 39 | 40 | del c:\php-sdk\locks\pickleweb-sync.lock >> %LOG_FILE% 2<&1 41 | 42 | :EXIT_LOCKED 43 | echo . 44 | 45 | -------------------------------------------------------------------------------- /bin/rmtools_setvars.bat-dist: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem RMTOOLS specific, not expected to depend on the SDK 4 | 5 | set PHP_RMTOOLS_PHP_SDK_ROOT_PATH=c:\php-snap-build\php-sdk 6 | 7 | set PHP_RMTOOLS_BIN_PATH=%~dp0 8 | set PHP_RMTOOLS_BIN_PATH=%PHP_RMTOOLS_BIN_PATH:~0,-1% 9 | 10 | for %%a in ("%PHP_RMTOOLS_BIN_PATH%") do set PHP_RMTOOLS_ROOT_PATH=%%~dpa 11 | rem remove trailing slash 12 | set PHP_RMTOOLS_ROOT_PATH=%PHP_RMTOOLS_ROOT_PATH:~0,-1% 13 | 14 | set PHP_RMTOOLS_SCRIPT_PATH=%PHP_RMTOOLS_ROOT_PATH%\script 15 | set PHP_RMTOOLS_LOCK_PATH=%PHP_RMTOOLS_ROOT_PATH%\locks 16 | set PHP_RMTOOLS_LOG_PATH=%PHP_RMTOOLS_ROOT_PATH%\logs 17 | set PHP_RMTOOLS_TMP_PATH=%PHP_RMTOOLS_ROOT_PATH%\tmp 18 | 19 | set PHP_RMTOOLS_PECL_IN_PKG_PATH=c:\php-snap-build\in-pkg\release 20 | set PHP_RMTOOLS_PECL_IN_PKG_NOMAIL_PATH=c:\php-snap-build\in-pkg\release-nomail 21 | set PHP_RMTOOLS_PECL_IN_SNAP_PATH=c:\php-snap-build\in-pkg\snap 22 | set PHP_RMTOOLS_PECL_IN_SNAP_NOMAIL_PATH=c:\php-snap-build\in-pkg\snap-nomail 23 | 24 | rem The below can be used to automate snaps against pre release of PHP or for 25 | rem the mass rebuild. For snaps against some pre PHP, adjust the rss watcher 26 | rem call with --enable-pre. For a mass rebuild, just put all the packages into 27 | rem the corresponding directory. This way, the regular builds and snaps will 28 | rem always have a higher priority over the pre or mass rebuild, thus the 29 | rem normal operation is not hurt. 30 | set PHP_RMTOOLS_PECL_IN_PKG_MASS_REBUILD_PATH=c:\php-snap-build\in-pkg\release-mass-rebuild 31 | set PHP_RMTOOLS_PECL_IN_PKG_MASS_REBUILD_NOMAIL_PATH=c:\php-snap-build\in-pkg\release-nomail-mass-rebuild 32 | set PHP_RMTOOLS_PECL_IN_SNAP_PRE_PATH=c:\php-snap-build\in-pkg\snap-pre 33 | set PHP_RMTOOLS_PECL_IN_SNAP_NOMAIL_PRE_PATH=c:\php-snap-build\in-pkg\snap-pre-nomail 34 | 35 | set PATH=%PHP_RMTOOLS_BIN_PATH%;%PATH% 36 | 37 | -------------------------------------------------------------------------------- /bin/snap-x64.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | if not exist %~dp0rmtools_setvars.bat ( 4 | echo RMTOOLS is not setup, create %~dp0rmtools_setvars.bat 5 | exit /b 3 6 | ) 7 | call %~dp0rmtools_setvars.bat 8 | 9 | call %PHP_RMTOOLS_PHP_SDK_ROOT_PATH%\phpsdk-vc15-x64.bat -t %PHP_RMTOOLS_BIN_PATH%\snapshot_task.bat --task-args "phpmaster all" 10 | 11 | -------------------------------------------------------------------------------- /bin/snap.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | rem must be on the env already 4 | if "%PHP_SDK_ROOT_PATH%"=="" ( 5 | echo PHP SDK is not setup 6 | exit /b 3 7 | ) 8 | call %~dp0rmtools_setvars.bat 9 | 10 | @ECHO ON 11 | call %PHP_SDK_PHP_CMD% %PHP_RMTOOLS_SCRIPT_PATH%\snap.php %* 12 | @ECHO OFF 13 | 14 | -------------------------------------------------------------------------------- /bin/snapshot_task.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | if not exist %~dp0rmtools_setvars.bat ( 4 | echo RMTOOLS is not setup, create %~dp0rmtools_setvars.bat 5 | exit /b 3 6 | ) 7 | 8 | rem must be on the env already 9 | if "%PHP_SDK_ROOT_PATH%"=="" ( 10 | echo PHP SDK is not setup 11 | exit /b 3 12 | ) 13 | call %~dp0rmtools_setvars.bat 14 | 15 | for /f "tokens=1-8 delims=-" %%a in ('powershell get-date -format "{yyyy-MM-dd-HH-mm-ss-ff}"') do set cur_date=%%a-%%b-%%c_%%d-%%e-%%f.%%g 16 | 17 | set PART=%* 18 | set LOG_FILE=%PHP_RMTOOLS_LOG_PATH%\task-%PART: =-%-%cur_date%.log 19 | set LOCK_FILE=%PHP_RMTOOLS_LOCK_PATH%\snaps.lock 20 | 21 | rem IF EXIST %LOCK_FILE% ( 22 | rem ECHO Snapshot script is already running. 23 | rem GOTO EXIT_LOCKED 24 | rem ) 25 | 26 | rem ECHO running > %LOCK_FILE% 27 | 28 | if not exist "%PHP_RMTOOLS_ROOT_PATH%\data\config\credentials_ftps.php" ( 29 | echo FTP config %PHP_SDK_ROOT_PATH%\data\config\credentials_ftps.php not found >> %LOG_FILE% 2<&1 30 | del %LOCK_FILE% >> %LOG_FILE% 2<&1 31 | exit /b 3 32 | ) 33 | 34 | call %PHP_RMTOOLS_BIN_PATH%\snap.bat %* >> %LOG_FILE% 2<&1 35 | 36 | rem del %LOCK_FILE% >> %LOG_FILE% 2<&1 37 | 38 | echo Done.>> %LOG_FILE% 39 | 40 | :EXIT_LOCKED 41 | echo . 42 | 43 | -------------------------------------------------------------------------------- /data/config.php: -------------------------------------------------------------------------------- 1 | '); 22 | } 23 | $this->config = new BranchConfig($config_path); 24 | $this->repo = Repository::fromBranchConfig($this->config); 25 | $this->repo->setModule($this->config->getModule()); 26 | $this->repo->setBranch($this->config->getRepoBranch()); 27 | $this->db_path = __DIR__ . '/../data/db/' . $this->config->getName() . '.json'; 28 | $this->required_builds_num = $required_builds_num; 29 | 30 | $this->data = $this->readData(); 31 | } 32 | 33 | protected function getEmptyData() 34 | { 35 | $data = new \StdClass; 36 | $data->revision_last = NULL; 37 | $data->revision_previous = NULL; 38 | $data->revision_last_exported = NULL; 39 | $data->build_num = 0; 40 | $data->builds = array(); 41 | 42 | return $data; 43 | } 44 | 45 | /* If both read and write are requested, read and yield data first. The fd 46 | is still open and the exclusive lock is held. Call the function once 47 | more to write. */ 48 | protected function atomicDataRW($read = true, $write = false, $truncate = false) 49 | { 50 | if ($write) { 51 | if ($truncate) { 52 | $open_mode = "wb+"; 53 | } else { 54 | $open_mode = "cb+"; 55 | } 56 | $lock_mode = LOCK_EX; 57 | } else { 58 | $open_mode = "rb"; 59 | $lock_mode = LOCK_SH; 60 | } 61 | 62 | if (!$this->db_fd) { 63 | $this->db_fd = fopen($this->db_path, $open_mode); 64 | if (!$this->db_fd) { 65 | $this->db_fd = NULL; 66 | throw new \Exception("Failed to open {$this->db_path}."); 67 | } 68 | flock($this->db_fd, $lock_mode); 69 | } 70 | 71 | if ($read) { 72 | rewind($this->db_fd); 73 | $j = ""; 74 | while(!feof($this->db_fd)) { 75 | $j .= fread($this->db_fd, 1024); 76 | } 77 | $data = json_decode($j); 78 | 79 | if (!$write) { 80 | flock($this->db_fd, LOCK_UN); 81 | fclose($this->db_fd); 82 | $this->db_fd = NULL; 83 | } 84 | return $data; 85 | } 86 | 87 | if ($write) { 88 | $json = json_encode($this->data, JSON_PRETTY_PRINT); 89 | $to_write = strlen($json); 90 | $wrote = 0; 91 | 92 | rewind($this->db_fd); 93 | do { 94 | $got = fwrite($this->db_fd, substr($json, $wrote)); 95 | if (false == $got) { 96 | break; 97 | } 98 | $wrote += $got; 99 | } while ($wrote < $to_write); 100 | 101 | if ($to_write !== $wrote) { 102 | flock($this->db_fd, LOCK_UN); 103 | fclose($this->db_fd); 104 | $this->db_fd = NULL; 105 | throw new Exception("Couldn't write '{$this->db_path}'"); 106 | } 107 | 108 | flock($this->db_fd, LOCK_UN); 109 | fclose($this->db_fd); 110 | $this->db_fd = NULL; 111 | 112 | return $wrote > 0; 113 | } 114 | } 115 | 116 | protected function readData() 117 | { 118 | try { 119 | $data = $this->atomicDataRW(true, false); 120 | } catch (\Exception $e) { 121 | $data = $this->getEmptyData(); 122 | } finally { 123 | if (!$data) { 124 | $data = $this->getEmptyData(); 125 | } 126 | } 127 | 128 | if ($data->build_num > $this->required_builds_num) { 129 | throw new \Exception("Inconsistent db, build number can't be {$data->build_num}."); 130 | } 131 | 132 | return $data; 133 | } 134 | 135 | protected function writeData() 136 | { 137 | return $this->atomicDataRW(false, true); 138 | } 139 | 140 | private function addBuildList($build_name = NULL) 141 | { 142 | $builds = $this->config->getBuildList(); 143 | 144 | if (!empty($builds)) { 145 | if ($build_name && "all" != $build_name) { 146 | if (in_array($build_name, $this->data->builds) && $this->hasUnfinishedBuild()) { 147 | throw new \Exception("Builds for '$build_name' are already done or in progress"); 148 | } 149 | $found = 0; 150 | foreach ($builds as $n => $v) { 151 | if ($n == $build_name) { 152 | $found = 1; 153 | $this->data->builds[] = $n; 154 | break; 155 | } 156 | } 157 | if (!$found) { 158 | throw new \Exception("Build name '$build_name' is not on the supported build list."); 159 | } 160 | } else { 161 | foreach ($builds as $n => $v) { 162 | if (in_array($n, $this->data->builds) && $this->hasUnfinishedBuild()) { 163 | throw new \Exception("Builds for '$n' are already done or in progress"); 164 | } 165 | $this->data->builds[] = $n; 166 | } 167 | } 168 | } else { 169 | throw new \Exception("No build configuration"); 170 | } 171 | } 172 | 173 | public function update($build_name = NULL) 174 | { 175 | try { 176 | $data = $this->atomicDataRW(true, true); 177 | } catch (\Exception $e) { 178 | $data = $this->getEmptyData(); 179 | } finally { 180 | if (!$data) { 181 | $data = $this->getEmptyData(); 182 | } 183 | } 184 | $this->data = $data; 185 | 186 | $last_id = $this->repo->getLastCommitId(); 187 | 188 | if (!$last_id) { 189 | flock($fd, LOCK_UN); 190 | fclose($fd); 191 | throw new \Exception("last revision id is empty"); 192 | } 193 | 194 | /* Update this only for the first build for the current revision. */ 195 | if (0 == $this->numBuildsRunning() && $this->hasNewRevision() || NULL == $this->data->revision_last) { 196 | $this->data->revision_previous = $this->data->revision_last; 197 | $this->data->revision_last = $last_id; 198 | } 199 | 200 | $this->addBuildList($build_name); 201 | 202 | 203 | return $this->atomicDataRW(false, true); 204 | 205 | } 206 | 207 | public function hasUnfinishedBuild() 208 | { 209 | return !$this->requiredBuildRunsReached() || $this->hasNewRevision(); 210 | } 211 | 212 | public function requiredBuildRunsReached() 213 | { 214 | $data = $this->readdata(); 215 | $this->data->build_num = $data->build_num; 216 | return $this->data->build_num == $this->required_builds_num; 217 | } 218 | 219 | public function hasNewRevision() 220 | { 221 | $last = $this->repo->getLastCommitId(); 222 | 223 | return $last && !$this->isLastRevisionExported($last) || is_null($this->data->revision_last); 224 | } 225 | 226 | public function export($revision = false, $build_type = false, $zip = false, $is_zip = false) 227 | { 228 | $rev_name = $revision ? $revision : $this->data->revision_last; 229 | if (strlen($rev_name) == 40) { 230 | $rev_name = substr($rev_name, 0, 7); 231 | } 232 | $dir_name = $this->config->getName() . '-src-' . ($build_type ? $build_type.'-' : $build_type) . 'r' . $rev_name; 233 | $build_dir = $this->config->getBuildDir(); 234 | if (!file_exists($build_dir)) { 235 | throw new \Exception("Directory '$build_dir' doesn't exist"); 236 | } 237 | $target = $build_dir . '/' . $dir_name; 238 | $exportfile = $this->repo->export($target, $rev_name); 239 | 240 | if (preg_match('/\.zip$/', $exportfile) > 0) { // export function returned a .zip file. 241 | $is_zip = true; 242 | } 243 | if ($zip && !$is_zip) { 244 | $zip_path = $dir_name . '.zip'; 245 | $cmd = "zip -q -r $zip_path $dir_name"; 246 | $res = exec_single_log($cmd, $build_dir); 247 | if (!$res) { 248 | throw new \Exception("Export failed, svn exec failed to be ran"); 249 | } 250 | } 251 | elseif ($is_zip === true) { 252 | $extract_dir = $build_dir . DIRECTORY_SEPARATOR . "$build_type-$rev_name-tmp-unzip"; 253 | while(is_dir($extract_dir)) { 254 | rmdir_rf($extract_dir); 255 | $extract_dir = $extract_dir . "-" . rand(0, 9); 256 | } 257 | if (true !== mkdir($extract_dir)) { 258 | throw new \Exception("Could not create temporary exctract dir under '$extract_dir'."); 259 | } 260 | 261 | $cmd = 'unzip -q -o ' . $exportfile . ' -d ' . $extract_dir; 262 | $res = exec_single_log($cmd); 263 | if (!$res) { 264 | throw new \Exception("Unzipping $exportfile failed."); 265 | } 266 | if (!$revision) { 267 | $gitname = $extract_dir . '/php-src-' . strtoupper($this->config->getName()) . '-' . $rev_name; 268 | } else { 269 | $gitname = $extract_dir . '/php-src-' . $rev_name; 270 | } 271 | while(is_dir($target)) { 272 | rmdir_rf($target); 273 | $target = $target . "-" . rand(0, 9); 274 | } 275 | if (true !== rename($gitname, $target)) { 276 | throw new \Exception("Failed to rename '$gitname' to '$target'"); 277 | } 278 | 279 | if (true !== rmdir($extract_dir)) { 280 | throw new \Exception("Could not remove temporary exctract dir under '$extract_dir'."); 281 | } 282 | } 283 | 284 | $target = realpath($target); 285 | return $target; 286 | } 287 | 288 | public function getLastCommitId() 289 | { 290 | return $this->repo->getLastCommitId(); 291 | } 292 | 293 | public function createSourceSnap($build_type = false, $revision = false) 294 | { 295 | return $this->export($revision, $build_type, true); 296 | } 297 | 298 | public function setLastRevisionExported($last_rev) 299 | { 300 | if ($this->requiredBuildRunsReached()) { 301 | $this->data->revision_last_exported = $last_rev; 302 | $this->writeData(); 303 | } 304 | } 305 | 306 | public function getLastRevisionExported() 307 | { 308 | return $this->data->revision_last_exported; 309 | } 310 | 311 | public function isLastRevisionExported($rev) 312 | { 313 | $last_exported = $this->getLastRevisionExported(); 314 | 315 | return $last_exported && substr_compare($rev, $last_exported, 0, strlen($last_exported)) === 0; 316 | } 317 | 318 | public function getLastRevisionId() 319 | { 320 | return $this->data->revision_last; 321 | } 322 | 323 | public function getPreviousRevision() 324 | { 325 | if (!$this->data->revision_previous) { 326 | return NULL; 327 | } 328 | return $this->data->revision_previous; 329 | } 330 | 331 | function getBuildList($platform) 332 | { 333 | /* XXX this might need to be changed, if the builds have to be done single at run. Then it'll 334 | need to check the thread safety argument as well. */ 335 | $builds = array(); 336 | foreach ($this->data->builds as $build_name) { 337 | $build = $this->config->getBuildFromName($build_name); 338 | if (isset($build['platform']) && $build['platform'] == $platform) { 339 | $builds[] = $build_name; 340 | } 341 | } 342 | return $builds; 343 | } 344 | 345 | function createBuildInstance($build_name) 346 | { 347 | $build = $this->config->getBuildFromName($build_name); 348 | 349 | if (!$build) { 350 | throw new \Exception("Invalid build name <$build_name>"); 351 | } 352 | 353 | $compiler = strtolower($build['compiler']); 354 | switch ($compiler) { 355 | case 'icc': 356 | case 'gcc': 357 | case 'clang': 358 | throw new \Exception("$compiler not supported yet. Not implemented."); 359 | default: 360 | $build = new BuildVC($this, $build_name); 361 | } 362 | 363 | return $build; 364 | } 365 | 366 | function buildFinished() 367 | { 368 | $this->data = $this->atomicDataRW(true, true); 369 | $this->data->build_num++; 370 | $this->atomicDataRW(false, true); 371 | } 372 | 373 | function resetBuildInfo() 374 | { 375 | if ($this->requiredBuildRunsReached()) { 376 | $this->data = $this->readData(); 377 | $this->data->build_num = 0; 378 | $this->data->builds = array(); 379 | $this->atomicDataRW(false, true, true); 380 | } 381 | } 382 | 383 | function numBuildsRunning() 384 | { 385 | return count($this->data->builds); 386 | } 387 | } 388 | -------------------------------------------------------------------------------- /include/BranchConfig.php: -------------------------------------------------------------------------------- 1 | 'configure_options', 8 | 'BuildDir' => 'build_dir', 9 | 'BuildLocation' => 'build_location', 10 | 'SourceDir' => 'source_dir', 11 | 'Include' => 'INCLUDE', 12 | 'Lib' => 'LIB', 13 | 'Path' => 'PATH', 14 | 'Compiler' => 'compiler', 15 | 'Architecture' => 'arch', 16 | 'Branch' => 'branch', 17 | 'Name' => 'name', 18 | 'RepoName' => 'repo_name', 19 | 'RepoBranch' => 'repo_branch', 20 | 'Module' => 'repo_module', 21 | 'PGO' => 'pgo', 22 | 'Debug' => 'debug', 23 | 'Appver' => 'appver', 24 | 'BuildSrcSubdir' => 'build_src_subdir', 25 | 'PeclDepsBase' => 'pecl_deps_base', 26 | 'CoreDepsBase' => 'core_deps_base', 27 | 'PeclNonCoreExtDepsBase' => 'pecl_non_core_ext_deps_base', 28 | 'Intrinsics' => 'intrinsics', 29 | ); 30 | 31 | function __construct($path) 32 | { 33 | //$this->config = parse_ini_file($path, false, INI_SCANNER_RAW); 34 | $this->config = parse_ini_file($path, true,INI_SCANNER_RAW); 35 | if (!$this->config) { 36 | throw new \Exception('Cannot parse config file <' . $path . '>'); 37 | } 38 | 39 | $builds = array(); 40 | 41 | foreach ($this->config as $name => $entry) { 42 | if (substr($name, 0, 6) == 'build-') { 43 | $name = str_ireplace('build-', '', $name); 44 | $builds[$name] = $entry; 45 | } 46 | } 47 | $this->builds = $builds; 48 | } 49 | 50 | function __call($name, $key) { 51 | $name = str_replace('get', '', $name); 52 | if (!isset($this->config_keys[$name])) { 53 | throw new \Exception("Invalid config entry name <$name>"); 54 | } 55 | 56 | $name = $this->config_keys[$name]; 57 | return (isset($this->config[$name]) ? $this->config[$name] : ''); 58 | } 59 | 60 | function getBuildList() 61 | { 62 | return $this->builds; 63 | } 64 | 65 | function getBuildFromName($build_name) { 66 | return isset($this->builds[$build_name]) ? $this->builds[$build_name] : NULL; 67 | } 68 | 69 | function getConfigureOptions($build_name) 70 | { 71 | if (isset($this->builds[$build_name]) && isset($this->builds[$build_name]['configure_options'])) { 72 | return $this->builds[$build_name]['configure_options']; 73 | } else { 74 | return ''; 75 | } 76 | } 77 | 78 | function getPgoScenarios($build_name) 79 | { 80 | if (!isset($this->builds[$build_name]) || !isset($this->builds[$build_name]["pgo_scenario"])) { 81 | /* TODO obtain all from SDK. */ 82 | return array("default", "cache"); 83 | } 84 | 85 | return explode(",", $this->builds[$build_name]["pgo_scenario"]); 86 | } 87 | 88 | function getPgoCases($build_name) 89 | { 90 | if (!isset($this->builds[$build_name]) || !isset($this->builds[$build_name]["pgo_cases"])) { 91 | return NULL; 92 | } 93 | 94 | return explode(",", $this->builds[$build_name]["pgo_cases"]); 95 | } 96 | 97 | public static function getRequiredBuildsNum($path, $branch) 98 | { 99 | $files = glob("$path/*/$branch.ini"); 100 | $i = 0; 101 | 102 | foreach ($files as $fname) { 103 | $cfg = parse_ini_file($fname, true, INI_SCANNER_RAW); 104 | foreach ($cfg as $name => $entry) { 105 | if (substr($name, 0, 6) == 'build-' && is_array($entry)) { 106 | $i++; 107 | } 108 | } 109 | } 110 | 111 | return $i; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /include/Build.php: -------------------------------------------------------------------------------- 1 | config->getBuildDir(); 36 | if (!file_exists($build_dir)) { 37 | throw new \Exception("Directory '$build_dir' doesn't exist"); 38 | } 39 | 40 | $this->branch = $branch; 41 | $this->build_name = $build_name; 42 | $this->obj_dir = $build_dir . '/' . $this->build_name; 43 | $this->compiler = $this->branch->config->getCompiler(); 44 | $this->architecture = $this->branch->config->getArchitecture(); 45 | 46 | $sdk_arch = getenv("PHP_SDK_ARCH"); 47 | if (strtolower($this->architecture) != strtolower($sdk_arch)) { 48 | throw new \Exception("Arch mismatch. PHP SDK is configured for '$sdk_arch', while the current RMTOOLS config targets '{$this->architecture}'"); 49 | } 50 | 51 | $sdk_vs = getenv("PHP_SDK_VS"); 52 | if (!$sdk_vs) { // fallback for versions before php-sdk-2.2.0beta4 53 | $sdk_vs = getenv("PHP_SDK_VC"); 54 | } 55 | if (strtolower($this->compiler) != strtolower($sdk_vs)) { 56 | throw new \Exception("Compiler mismatch. PHP SDK is configured for '$sdk_vs', while the current RMTOOLS config targets '{$this->compiler}'"); 57 | } 58 | 59 | $env = getenv(); 60 | /*$env = array(); 61 | $env['PATH'] = getenv('PATH') ; 62 | $env['INCLUDE'] = getenv('INCLUDE'); 63 | $env['LIB'] = getenv('LIB'); 64 | 65 | $env['TMP'] = $env['TEMP'] = getenv('TEMP'); 66 | $env['SystemDrive'] = getenv('SystemDrive'); 67 | $env['SystemRoot'] = getenv('SystemRoot'); */ 68 | 69 | /* XXX Not sure, in how far the below is needed. */ 70 | /* 71 | $env['CPU'] = "i386"; 72 | $env['APPVER'] = "5.01"; // setenv /xp 73 | if (strcasecmp($this->architecture, 'x64') == 0) { 74 | $env['CPU'] = "AMD64"; 75 | } 76 | if (strcmp($branch->config->getAppver(), '2008') == 0) { 77 | $env['APPVER'] = "6.0"; 78 | } 79 | */ 80 | if ($branch->config->getDebug() == 0) { 81 | $env['NODEBUG'] = "1"; 82 | } 83 | 84 | $env["PHP_RMTOOLS_PHP_BUILD_BRANCH"] = $this->branch->config->getBranch(); 85 | 86 | $this->env = $env; 87 | 88 | $this->pgo_init_lock_fd = NULL; 89 | } 90 | 91 | function setSourceDir($src_dir) 92 | { 93 | $this->build_dir = $src_dir; 94 | } 95 | 96 | private function addLogsToArchive() 97 | { 98 | $zip = new \ZipArchive(); 99 | if ($zip->open($this->archive_path) === FALSE) { 100 | throw new \Exception('cannot open archive'); 101 | } 102 | $zip->addFromString('logs\buildconf.txt', $this->log_buildconf); 103 | $zip->addFromString('logs\configure.txt', $this->log_configure); 104 | $zip->addFromString('logs\make.txt', $this->log_make); 105 | $zip->addFromString('logs\archive.txt', $this->log_archive); 106 | $zip->close(); 107 | } 108 | 109 | function updateDeps(string $stability = "stable") 110 | { 111 | $branch = $this->branch->config->getBranch(); 112 | $compiler = $this->branch->config->getCompiler(); 113 | $cmd = "phpsdk_deps -un -s $stability -b $branch -t $compiler -d " . dirname($this->build_dir) . "/deps"; 114 | $ret = exec_single_log($cmd, $this->build_dir, $this->env); 115 | if (!$ret || 0 !== (int)$ret["return_value"]) { 116 | throw new \Exception('dependencies update failed' . (isset($ret["log"]) ? ": \n$ret[log]" : "")); 117 | } 118 | 119 | return $ret; 120 | } 121 | 122 | function buildconf() 123 | { 124 | $cmd = 'buildconf'; 125 | $ret = exec_single_log($cmd, $this->build_dir, $this->env); 126 | if (!$ret || 0 !== (int)$ret["return_value"]) { 127 | throw new \Exception('buildconf failed' . (isset($ret["log"]) ? ": \n$ret[log]" : "")); 128 | } 129 | $this->log_buildconf = $ret['log']; 130 | } 131 | 132 | function pgoInitLock() 133 | { 134 | if (is_null($this->pgo_init_lock_fd)) { 135 | $fn = TMP_DIR . DIRECTORY_SEPARATOR . "sdk_pgo_init.lock"; 136 | $this->pgo_init_lock_fd = fopen($fn, "wb"); 137 | if (false == $this->pgo_init_lock_fd) { 138 | throw new \Exception("Failed to create lock under '$fn'"); 139 | } 140 | flock($this->pgo_init_lock_fd, LOCK_EX); 141 | } 142 | } 143 | 144 | function pgoInitUnlock() 145 | { 146 | if (!is_null($this->pgo_init_lock_fd)) { 147 | flock($this->pgo_init_lock_fd, LOCK_UN); 148 | @unlink(TMP_DIR . DIRECTORY_SEPARATOR . "sdk_pgo_init.lock"); 149 | $this->pgo_init_lock_fd = NULL; 150 | } 151 | } 152 | 153 | function isPgoSetup() 154 | { 155 | $env = $this->env; 156 | $env["Path"] = dirname($this->build_dir) . DIRECTORY_SEPARATOR . "deps" . DIRECTORY_SEPARATOR . "bin;" . $env["Path"]; 157 | 158 | $cmd = 'phpsdk_pgo --ready'; 159 | $ret = exec_single_log($cmd, $this->build_dir, $env); 160 | if (!$ret) { 161 | $this->pgoInitUnlock(); 162 | throw new \Exception('phpsdk_pgo --ready failed' . (isset($ret["log"]) ? ": \n$ret[log]" : "")); 163 | } 164 | 165 | return 0 == (int)$ret["return_value"]; 166 | } 167 | 168 | function pgoInit() 169 | { 170 | $this->log_pgo = isset($this->log_pgo) ? $this->log_pgo . "\n" : ""; 171 | $env = $this->env; 172 | $env["Path"] = dirname($this->build_dir) . DIRECTORY_SEPARATOR . "deps" . DIRECTORY_SEPARATOR . "bin;" . $env["Path"]; 173 | 174 | $cmd = 'phpsdk_pgo --init'; 175 | $ret = exec_single_log($cmd, $this->build_dir, $env); 176 | if (!$ret || 0 !== (int)$ret["return_value"]) { 177 | $this->pgoInitUnlock(); 178 | throw new \Exception('phpsdk_pgo --init failed' . (isset($ret["log"]) ? ": \n$ret[log]" : "")); 179 | } 180 | $this->log_pgo .= $ret["log"]; 181 | } 182 | 183 | function pgoTrain() 184 | { 185 | $this->log_pgo = isset($this->log_pgo) ? $this->log_pgo . "\n" : ""; 186 | $env = $this->env; 187 | $env["Path"] = dirname($this->build_dir) . DIRECTORY_SEPARATOR . "deps" . DIRECTORY_SEPARATOR . "bin;" . $env["Path"]; 188 | 189 | foreach ($this->branch->config->getPgoScenarios($this->build_name) as $scenario) { 190 | $cases = $this->branch->config->getPgoCases($this->build_name); 191 | $cmd = 'phpsdk_pgo --train --scenario=' . $scenario . ($cases ? (" --cases=" . implode(",", $cases)) : ""); 192 | $ret = exec_single_log($cmd, $this->build_dir, $env); 193 | if (!$ret || 0 !== (int)$ret["return_value"]) { 194 | if ($ret["log"]) { 195 | $this->log_pgo .= $ret["log"]; 196 | } 197 | throw new \Exception("'$cmd' failed" . (isset($ret["log"]) ? ": \n$ret[log]" : "")); 198 | } 199 | $this->log_pgo .= $ret["log"]; 200 | } 201 | } 202 | 203 | function configure($extra = false, $rm_obj = true) 204 | { 205 | $args = $this->branch->config->getConfigureOptions($this->build_name) . ($extra ?: $extra); 206 | $cmd = 'configure ' . $args . ' --enable-object-out-dir=' . $this->obj_dir; 207 | /* old build may have been stoped */ 208 | if (is_dir($this->obj_dir) && $rm_obj === true) { 209 | rmdir_rf($this->obj_dir); 210 | } 211 | if (!is_dir($this->obj_dir)) { 212 | mkdir($this->obj_dir, 0655, true); 213 | } 214 | $ret = exec_single_log($cmd, $this->build_dir, $this->env); 215 | if (!$ret || 0 !== (int)$ret["return_value"]) { 216 | throw new \Exception('Configure failed' . (isset($ret["log"]) ? ": \n$ret[log]" : "")); 217 | } 218 | $this->log_configure = $ret['log']; 219 | } 220 | 221 | function make($target = false) 222 | { 223 | $cmd = 'nmake /nologo' . ($target ?: $target); 224 | $ret = exec_single_log($cmd, $this->build_dir, $this->env); 225 | if (!$ret || 0 !== (int)$ret["return_value"]) { 226 | throw new \Exception('Make failed' . (isset($ret["log"]) ? ": \n$ret[log]" : "")); 227 | } 228 | $this->log_make = $ret['log']; 229 | } 230 | 231 | function makeArchive() 232 | { 233 | $cmd = 'nmake /nologo snap'; 234 | $ret = exec_single_log($cmd, $this->build_dir, $this->env); 235 | if (!$ret || 0 !== (int)$ret["return_value"]) { 236 | throw new \Exception('Make snap failed' . (isset($ret["log"]) ? ": \n$ret[log]" : "")); 237 | } 238 | 239 | $this->log_archive = $ret['log']; 240 | 241 | if (!preg_match('/Build dir: (.*)/', $this->log_configure, $matches)) { 242 | throw new \Exception('Make archive failed, cannot find build dir'); 243 | } 244 | $zip_dir = trim($matches[1]); 245 | 246 | if (!preg_match('/.*(php-\d\.\d\.\d.*\.zip)/', $this->log_archive, $matches)) { 247 | throw new \Exception('Make archive failed, cannot find php archive'); 248 | } 249 | $zip_filename = trim($matches[1]); 250 | 251 | if (!preg_match('/.*(php-devel-pack-\d\.\d\.\d.*\.zip)/', $this->log_archive, $matches)) { 252 | throw new \Exception('Make archive failed, cannot find php-devel archive'); 253 | } 254 | $zip_devel_filename = trim($matches[1]); 255 | $this->zip_devel_filename = $zip_devel_filename; 256 | 257 | if (!preg_match('/.*(php-debug-pack-\d\.\d\.\d.*\.zip)/', $this->log_archive, $matches)) { 258 | throw new \Exception('Make archive failed, cannot find php-debug archive'); 259 | } 260 | $zip_debug_filename = trim($matches[1]); 261 | $this->zip_debug_filename = $zip_debug_filename; 262 | 263 | if (!preg_match('/.*(php-test-pack-\d\.\d\.\d.*\.zip)/', $this->log_archive, $matches)) { 264 | throw new \Exception('Make archive failed, cannot find php-test archive'); 265 | } 266 | $zip_test_filename = trim($matches[1]); 267 | $this->zip_test_filename = $zip_test_filename; 268 | 269 | $this->archive_path = realpath($zip_dir . '/' . $zip_filename); 270 | $this->debug_path = realpath($zip_dir . '/' . $zip_debug_filename); 271 | $this->devel_path = realpath($zip_dir . '/' . $zip_devel_filename); 272 | $this->test_path = realpath($zip_dir . '/' . $zip_test_filename); 273 | 274 | $this->addLogsToArchive(); 275 | } 276 | 277 | function getMakeLogParsed() 278 | { 279 | $parser = new MakeLogParserVc; 280 | $tmpfile = $this->obj_dir . '/' . 'make.txt'; 281 | file_put_contents($tmpfile, $this->log_make); 282 | $parser->parse($tmpfile, $this->build_dir); 283 | unlink($tmpfile); 284 | $this->stats = $parser->stats; 285 | $this->compiler_log_parser = $parser; 286 | return $parser->toHtml($this->build_name); 287 | } 288 | 289 | function getStats() 290 | { 291 | return $this->stats; 292 | } 293 | 294 | function clean() 295 | { 296 | rmdir_rf($this->obj_dir); 297 | } 298 | 299 | function getLogs() 300 | { 301 | 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /include/Git.php: -------------------------------------------------------------------------------- 1 | repo_url = $repo_url; 15 | $this->gh_url = $gh_url; 16 | 17 | if (!file_exists($this->git_cmd)) { 18 | $git_cmd = trim(shell_exec("where git.exe")); 19 | if (!$git_cmd) { 20 | throw new \Exception("Git binary not available"); 21 | } 22 | $this->git_cmd = $git_cmd; 23 | } 24 | 25 | if (!file_exists($this->tar_cmd)) { 26 | $tar_cmd = trim(shell_exec("where tar.exe")); 27 | if (!$tar_cmd) { 28 | throw new \Exception("Tar binary not available"); 29 | } 30 | $this->tar_cmd = $tar_cmd; 31 | } 32 | } 33 | 34 | function setModule($module) { 35 | $this->module = $module; 36 | } 37 | 38 | function setBranch($branch) { 39 | $this->branch = $branch; 40 | } 41 | 42 | public function export($dest, $revision = false) 43 | { 44 | $rev = $revision ? $revision : $this->branch; 45 | if (isset($this->gh_url)) { 46 | $url = $this->gh_url . '/zip/' . $rev; 47 | } else { 48 | $http_url = preg_replace('/git:\/\//', 'http://', $this->repo_url); 49 | $url = $http_url . '/?p=' . $this->module . ';a=snapshot;h=' . $rev . ';sf=zip'; 50 | } 51 | $dest .= '.zip'; 52 | wget($url, $dest); 53 | return $dest; 54 | } 55 | 56 | public function info() 57 | { 58 | } 59 | 60 | public function getLastCommitId() 61 | { 62 | $try = 3; 63 | $cmd = '"' . $this->git_cmd . '" ls-remote ' . $this->repo_url . '/' . $this->module . ' ' . $this->branch; 64 | while ( $try > 0 ) { 65 | $res = exec_sep_log($cmd); 66 | if ($res && !empty($res['log_stdout'])) { 67 | break; 68 | } 69 | $try--; 70 | } 71 | if ($res && $res['return_value'] != 0) { 72 | throw new \Exception('git ls-remote failed <' . $this->repo_url . '/' . $this->module . ' ' . $this->branch . '>, ' . $res['log_stderr']); 73 | } 74 | 75 | $revision = preg_replace("/[\s\t]+.+/", "", $res['log_stdout']); 76 | $revision = trim($revision); 77 | return (string)$revision; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /include/MakeLogParser.php: -------------------------------------------------------------------------------- 1 | log; 14 | ob_start(); 15 | include __DIR__ . '/../template/make_log.tpl.php'; 16 | $html = ob_get_contents(); 17 | ob_end_clean(); 18 | return $html; 19 | } 20 | 21 | function getErrors() 22 | { 23 | if ($this->stats['error'] > 0) { 24 | $res = array(); 25 | foreach ($this->log as $e) { 26 | if ($e['level'] == 'error' || $e['level'] == 'fatal') { 27 | $res[] = $e; 28 | } 29 | } 30 | return $res; 31 | } else { 32 | return NULL; 33 | } 34 | } 35 | 36 | function diff($prev) { 37 | $result = array(); 38 | 39 | foreach ($cur as $k => $v) { 40 | if (array_key_exists($k, $prev)) { 41 | if (is_array($v)) { 42 | $tmp_ar = log_diff($v, $prev[$k]); 43 | if (count($tmp_ar)) { $result[$k] = $tmp_ar; } 44 | } else { 45 | if ($v != $prev[$k]) { 46 | $result[$k] = $v; 47 | } 48 | } 49 | } else { 50 | $result[$k] = $v; 51 | } 52 | } 53 | 54 | return $result; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /include/MakeLogParserVC.php: -------------------------------------------------------------------------------- 1 | stats = array('warning' => 0, 'error' => 0); 9 | $lines = file($path); 10 | if (empty($lines)) { 11 | return NULL; 12 | } 13 | $line_nr = 1; 14 | 15 | if ($root_src_dir && $root_src_dir[strlen($root_src_dir) -1] != '\\') { 16 | $root_src_dir .= '\\'; 17 | } 18 | 19 | //win32\build\deplister.c(50) : warning C4090: 'function' : different 'const' qualifiers 20 | $pcre = '/(error|warning)/'; 21 | $log = array(); 22 | foreach ($lines as $line) { 23 | $file = ''; 24 | $level = ''; 25 | /* $out = '#' . ($line_nr++) . ' ';*/ 26 | $res = preg_match($pcre, $line); 27 | if ($res) { 28 | /* absolute path + error/warning */ 29 | $txt = $line; 30 | $re1='([a-z]:\\\\(?:[-\\w\\.\\d]+\\\\)*(?:[-\\w\\.\\d]+)?)'; # Windows Path 1 31 | $re2='.*?'; # Non-greedy match on filler 32 | $re3='(\\d+)'; # Integer Number 1 33 | $re4='.*?'; # Non-greedy match on filler 34 | $re5='((?:[a-z][a-z]+))'; # Word 1 35 | $re6='.*?'; # Non-greedy match on filler 36 | $re7='((?:[a-z][a-z]*[0-9]+[a-z0-9]*))'; # Alphanum 1 37 | $re8 =':(.*?)$'; 38 | if (preg_match_all ("/".$re1.$re2.$re3.$re4.$re5.$re6.$re7.$re8."/is", $txt, $matches)) 39 | { 40 | $winpath1 = $matches[1][0]; 41 | $int1 = $matches[2][0]; 42 | $word1 = $matches[3][0]; 43 | $alphanum1 = $matches[4][0]; 44 | $error_msg = trim(str_replace(array("\r","\n"), array('',''),$matches[5][0])); 45 | $row = array( 46 | 'file' => $winpath1, 47 | 'line' => $int1, 48 | 'level' => $word1, 49 | 'code' => $alphanum1, 50 | 'message' => $error_msg 51 | ); 52 | } else { 53 | /* relative path + error/warning */ 54 | $re1='(.*?)'; # Non-greedy match on filler 55 | $re2=''; # Uninteresting: int 56 | $re3=''; # Non-greedy match on filler 57 | $re4='\((\\d+)\)'; # Integer Number 1 58 | $re5='.*?'; # Non-greedy match on filler 59 | $re6='((?:[a-z][a-z]+))'; # Word 1 60 | $re7='.*?'; # Non-greedy match on filler 61 | $re8='((?:[a-z][a-z]*[0-9]+[a-z0-9]*))'; # Alphanum 1 62 | $re9 =':(.*?)$'; 63 | 64 | if (preg_match_all ("/".$re1.$re2.$re3.$re4.$re5.$re6.$re7.$re8.$re9."/is", $txt, $matches)) 65 | { 66 | $path=$matches[1][0]; 67 | $int1=$matches[2][0]; 68 | $word1=$matches[3][0]; 69 | $alphanum1=$matches[4][0]; 70 | $error_msg=trim(str_replace(array("\r","\n"), array('',''),$matches[5][0])); 71 | /** @noinspection PhpUnusedLocalVariableInspection */ 72 | /*$out .= "match 2: ($path) ($int1) ($word1) ($alphanum1) ($error_msg)\n";*/ 73 | $row = array( 74 | 'file' => $path, 75 | 'line' => $int1, 76 | 'level' => $word1, 77 | 'code' => $alphanum1, 78 | 'message' => $error_msg 79 | ); 80 | } else { 81 | /* cl.exe, link, etc. + error/warning */ 82 | $re1='((?:[a-z][a-z]+))'; # Word 1 83 | $re2='.*?'; # Non-greedy match on filler 84 | $re3='((?:[a-z][a-z]+))'; # Word 2 85 | $re4='.*?'; # Non-greedy match on filler 86 | $re5='((?:[a-z][a-z]*[0-9]+[a-z0-9]*))'; # Alphanum 1 87 | $re6 =':(.*?)$'; 88 | 89 | if (preg_match_all ("/".$re1.$re2.$re3.$re4.$re5.$re6."/is", $txt, $matches)) 90 | { 91 | $word1=$matches[1][0]; 92 | $word2=$matches[2][0]; 93 | $alphanum1=$matches[3][0]; 94 | 95 | $error_msg = trim(str_replace(array("\r","\n"), array('',''), $matches[4][0])); 96 | /* $out .= "match 3: ($word1) ($word2) ($alphanum1) ($error_msg)\n";*/ 97 | if (substr($alphanum1, 0, 3) == 'LNK') { 98 | if (strpos($txt, '.lib') || strpos($txt, '.obj')) { 99 | $pos = strpos($txt, ':'); 100 | $file = substr($txt, 0, $pos); 101 | $re = preg_match('/^.*: (warning|error) LNK[0-9]+:.*$/', $txt, $matches); 102 | if ($re) { 103 | $level = $matches[1]; 104 | } else { 105 | $level = ''; 106 | } 107 | } 108 | } 109 | 110 | $row = array( 111 | 'file' => $file, 112 | 'line' => '', 113 | 'level' => $level, 114 | 'code' => $alphanum1, 115 | 'message' => $error_msg 116 | ); 117 | } else { 118 | $row = array( 119 | 'file' => '', 120 | 'line' => '', 121 | 'level' => '', 122 | 'code' => '', 123 | 'message' => $txt 124 | ); 125 | } 126 | } 127 | } 128 | } else { 129 | continue; 130 | } 131 | 132 | $row['file'] = str_ireplace($root_src_dir, '', $row['file']); 133 | $row['section'] = strtolower(dirname($row['file'])); 134 | $row['file'] = str_ireplace($row['section'] . '\\', '', $row['file']); 135 | if ($row['level'] == 'fatal') { 136 | $row['level'] = 'error'; 137 | } 138 | 139 | if (isset($this->stats[$row['level']])) { 140 | $this->stats[$row['level']]++; 141 | } 142 | $log[] = $row; 143 | } 144 | $this->log = $log; 145 | return true; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /include/PeclBranch.php: -------------------------------------------------------------------------------- 1 | '); 15 | } 16 | $this->config = new BranchConfig($config_path); 17 | $this->addBuildList(); 18 | } 19 | 20 | private function addBuildList() 21 | { 22 | $builds = $this->config->getBuildList(); 23 | 24 | if (!empty($builds)) { 25 | $this->builds = array(); 26 | foreach ($builds as $n => $v) { 27 | $this->builds[] = $n; 28 | } 29 | } else { 30 | $this->builds = NULL; 31 | } 32 | } 33 | 34 | public function update() 35 | { 36 | // pass 37 | } 38 | 39 | public function hasNewRevision() 40 | { 41 | return false; 42 | } 43 | 44 | public function export($revision = false, $build_type = false, $zip = false, $is_zip = false) 45 | { 46 | // TODO 47 | } 48 | 49 | public function createSourceSnap($build_type = false, $revision = false) 50 | { 51 | return $this->export($revision, $build_type, true); 52 | } 53 | 54 | public function setLastRevisionExported($last_rev) 55 | { 56 | // pass 57 | } 58 | 59 | public function getLastRevisionExported() 60 | { 61 | return NULL; 62 | } 63 | 64 | public function getLastRevisionId() 65 | { 66 | return NULL; 67 | } 68 | 69 | public function getPreviousRevision() 70 | { 71 | return NULL; 72 | } 73 | 74 | function getBuildList($platform) 75 | { 76 | $builds = array(); 77 | foreach ($this->builds as $build_name) { 78 | $build = $this->config->getBuildFromName($build_name); 79 | if (isset($build['platform']) && $build['platform'] == $platform) { 80 | $builds[] = $build_name; 81 | } 82 | } 83 | return $builds; 84 | } 85 | 86 | function createBuildInstance($build_name) 87 | { 88 | $build = NULL; 89 | $build_config = $this->config->getBuildFromName($build_name); 90 | 91 | if (!$build_config) { 92 | throw new \Exception("Invalid build name <$build_name>"); 93 | } 94 | 95 | $compiler = strtolower($build_config['compiler']); 96 | switch ($compiler) { 97 | case 'vs16': 98 | case 'vc15': 99 | case 'vc14': 100 | case 'vc12': 101 | case 'vc11': 102 | $build = new PeclBuildVC($this, $build_name); 103 | break; 104 | case 'icc': 105 | case 'gcc': 106 | case 'clang': 107 | default: 108 | throw new \Exception("$compiler not supported yet. Not implemented"); 109 | break; 110 | } 111 | 112 | return $build; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /include/PeclBuildVC.php: -------------------------------------------------------------------------------- 1 | config->getBuildDir(); 35 | if (!file_exists($build_dir)) { 36 | throw new \Exception("Directory '$build_dir' doesn't exist"); 37 | } 38 | 39 | $this->branch = $branch; 40 | $this->build_name = $build_name; 41 | $this->obj_dir = $build_dir . '/' . $branch->config->getBranch() . '-' . $this->build_name; 42 | $this->compiler = $branch->config->builds[$build_name]['compiler']; 43 | $this->architecture = $branch->config->builds[$build_name]['arch']; 44 | $this->thread_safe = (boolean)$branch->config->builds[$build_name]['thread_safe']; 45 | 46 | $sdk_arch = getenv("PHP_SDK_ARCH"); 47 | if (strtolower($this->architecture) != strtolower($sdk_arch)) { 48 | throw new \Exception("Arch mismatch. PHP SDK is configured for '$sdk_arch', while the current RMTOOLS config targets '{$this->architecture}'"); 49 | } 50 | 51 | $sdk_vs = getenv("PHP_SDK_VS"); 52 | if (!$sdk_vs) { // fallback for versions before php-sdk-2.2.0beta4 53 | $sdk_vs = getenv("PHP_SDK_VC"); 54 | } 55 | if (strtolower($this->compiler) != strtolower($sdk_vs)) { 56 | throw new \Exception("Compiler mismatch. PHP SDK is configured for '$sdk_vs', while the current RMTOOLS config targets '{$this->compiler}'"); 57 | } 58 | 59 | $env = getenv(); 60 | /*$env = array(); 61 | $env['PATH'] = getenv('PATH') ; 62 | $env['INCLUDE'] = getenv('INCLUDE'); 63 | $env['LIB'] = getenv('LIB'); 64 | 65 | $env['TMP'] = $env['TEMP'] = getenv('TEMP'); 66 | $env['SystemDrive'] = getenv('SystemDrive'); 67 | $env['SystemRoot'] = getenv('SystemRoot');*/ 68 | 69 | /* XXX Not sure, in how far the below is needed. */ 70 | /* 71 | $env['CPU'] = "i386"; 72 | $env['APPVER'] = "5.01"; // setenv /xp 73 | if (strcasecmp($this->architecture, 'x64') == 0) { 74 | $env['CPU'] = "AMD64"; 75 | } 76 | if (strcmp($branch->config->getAppver(), '2008') == 0) { 77 | $env['APPVER'] = "6.0"; 78 | } 79 | */ 80 | if ($branch->config->getDebug() == 0) { 81 | $env['NODEBUG'] = "1"; 82 | } 83 | 84 | $this->env = $env; 85 | } 86 | 87 | function addPath($path) 88 | { 89 | if (isset($this->env["PATH"])) { 90 | $this->env["PATH"] = $path . ";" . $this->env["PATH"]; 91 | } else if (isset($this->env["Path"])) { 92 | $this->env["Path"] = $path . ";" . $this->env["Path"]; 93 | } 94 | } 95 | 96 | function setSourceDir($src_dir) 97 | { 98 | $this->build_dir = $src_dir; 99 | } 100 | 101 | function getSourceDir() 102 | { 103 | return $this->build_dir; 104 | } 105 | 106 | private function addLogsToArchive() 107 | { 108 | $zip = new \ZipArchive(); 109 | if ($zip->open($this->archive_path) === FALSE) { 110 | throw new \Exception('cannot open archive'); 111 | } 112 | $zip->addFromString('logs\buildconf.txt', $this->log_buildconf); 113 | $zip->addFromString('logs\configure.txt', $this->log_configure); 114 | $zip->addFromString('logs\make.txt', $this->log_make); 115 | $zip->addFromString('logs\archive.txt', $this->log_archive); 116 | $zip->close(); 117 | } 118 | 119 | function buildconf() 120 | { 121 | $cmd = 'buildconf'; 122 | $ret = exec_single_log($cmd, $this->build_dir, $this->env); 123 | if (!$ret) { 124 | throw new \Exception('buildconf failed'); 125 | } 126 | $this->log_buildconf = $ret['log']; 127 | } 128 | 129 | function configure($extra = false, $rm_obj = true) 130 | { 131 | $args = $this->branch->config->getConfigureOptions($this->build_name) . ($extra ?: $extra); 132 | $cmd = 'configure ' . $args . ' --enable-object-out-dir=' . $this->obj_dir; 133 | /* old build may have been stoped */ 134 | if (is_dir($this->obj_dir) && $rm_obj === true) { 135 | rmdir_rf($this->obj_dir); 136 | } 137 | mkdir($this->obj_dir, 0655, true); 138 | $ret = exec_single_log($cmd, $this->build_dir, $this->env); 139 | if (!$ret) { 140 | throw new \Exception('Configure failed'); 141 | } 142 | $this->log_configure = $ret['log']; 143 | } 144 | 145 | function make($target = false) 146 | { 147 | $cmd = 'nmake /nologo' . ($target ?: $target); 148 | $ret = exec_single_log($cmd, $this->build_dir, $this->env); 149 | if (!$ret) { 150 | throw new \Exception('Make failed'); 151 | } 152 | $this->log_make = $ret['log']; 153 | } 154 | 155 | function makeArchive() 156 | { 157 | $cmd = 'nmake /nologo snap'; 158 | $ret = exec_single_log($cmd, $this->build_dir, $this->env); 159 | if (!$ret) { 160 | throw new \Exception('Make snap failed'); 161 | } 162 | 163 | $this->log_archive = $ret['log']; 164 | 165 | if (!preg_match('/Build dir: (.*)/', $this->log_configure, $matches)) { 166 | throw new \Exception('Make archive failed, cannot find build dir'); 167 | } 168 | $zip_dir = trim($matches[1]); 169 | 170 | if (!preg_match('/.*(php-\d\.\d\.\d.*\.zip)/', $this->log_archive, $matches)) { 171 | throw new \Exception('Make archive failed, cannot find php archive'); 172 | } 173 | $zip_filename = trim($matches[1]); 174 | 175 | if (!preg_match('/.*(php-devel-pack-\d\.\d\.\d.*\.zip)/', $this->log_archive, $matches)) { 176 | throw new \Exception('Make archive failed, cannot find php-devel archive'); 177 | } 178 | $zip_devel_filename = trim($matches[1]); 179 | $this->zip_devel_filename = $zip_devel_filename; 180 | 181 | if (!preg_match('/.*(php-debug-pack-\d\.\d\.\d.*\.zip)/', $this->log_archive, $matches)) { 182 | throw new \Exception('Make archive failed, cannot find php-debug archive'); 183 | } 184 | $zip_debug_filename = trim($matches[1]); 185 | $this->zip_debug_filename = $zip_debug_filename; 186 | 187 | if (!preg_match('/.*(php-test-pack-\d\.\d\.\d.*\.zip)/', $this->log_archive, $matches)) { 188 | throw new \Exception('Make archive failed, cannot find php-test archive'); 189 | } 190 | $zip_test_filename = trim($matches[1]); 191 | $this->zip_test_filename = $zip_test_filename; 192 | 193 | $this->archive_path = realpath($zip_dir . '/' . $zip_filename); 194 | $this->debug_path = realpath($zip_dir . '/' . $zip_debug_filename); 195 | $this->devel_path = realpath($zip_dir . '/' . $zip_devel_filename); 196 | $this->test_path = realpath($zip_dir . '/' . $zip_test_filename); 197 | 198 | $this->addLogsToArchive(); 199 | } 200 | 201 | function getMakeLogParsed() 202 | { 203 | $parser = new MakeLogParserVc; 204 | $tmpfile = $this->obj_dir . '/' . 'make.txt'; 205 | file_put_contents($tmpfile, $this->log_make); 206 | $parser->parse($tmpfile, $this->build_dir); 207 | unlink($tmpfile); 208 | $this->stats = $parser->stats; 209 | $this->compiler_log_parser = $parser; 210 | return $parser->toHtml($this->build_name); 211 | } 212 | 213 | function getStats() 214 | { 215 | return $this->stats; 216 | } 217 | 218 | function clean() 219 | { 220 | rmdir_rf($this->obj_dir); 221 | } 222 | 223 | function getLogs() 224 | { 225 | 226 | } 227 | 228 | function getObjDir() 229 | { 230 | return $this->obj_dir; 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /include/PeclDb.php: -------------------------------------------------------------------------------- 1 | open($db_path); 18 | 19 | if (!$existent && $autoinit) { 20 | $this->initDb(); 21 | } 22 | } 23 | 24 | public function initDb() 25 | { 26 | $sql = "CREATE TABLE ext_release (ext_name STRING, ext_version STRING, ts_built INTEGER);"; 27 | $this->exec($sql); 28 | 29 | } 30 | 31 | public function add($name, $version, $force = false) 32 | { 33 | if ($force) { 34 | $this->remove($name, $version); 35 | } 36 | 37 | if ($this->exists($name, $version)) { 38 | return false; 39 | } 40 | 41 | $name = $this->escapeString($name); 42 | $version = $this->escapeString($version); 43 | $sql = "INSERT INTO ext_release (ext_name, ext_version, ts_built) VALUES ('$name', '$version', 0);"; 44 | $this->exec($sql); 45 | 46 | return true; 47 | } 48 | 49 | public function remove($name, $version) 50 | { 51 | $name = $this->escapeString($name); 52 | $version = $this->escapeString($version); 53 | $sql = "DELETE FROM ext_release WHERE ext_name = '$name' AND ext_version = '$version';"; 54 | $this->exec($sql); 55 | } 56 | 57 | public function exists($name, $version, $where = '') 58 | { 59 | /* cant check such thing, so trust :) */ 60 | if ($where) { 61 | $where = "AND $where"; 62 | } 63 | 64 | $name = $this->escapeString($name); 65 | $version = $this->escapeString($version); 66 | $sql = "SELECT ts_built FROM ext_release WHERE ext_name = '$name' AND ext_version = '$version' $where;"; 67 | 68 | $res = $this->query($sql); 69 | 70 | $ret = false !== $res->fetchArray(SQLITE3_NUM); 71 | //return $res->numColumns() > 0; 72 | 73 | $res->finalize(); 74 | 75 | return $ret; 76 | } 77 | 78 | public function done($name, $version) 79 | { 80 | /* XXX That's an assumption as the latest timestamp should be about 30 mit old. 81 | Need to extend pecl.php to set the real statuses when in't really done */ 82 | return $this->exists($name, $version, "ts_built - " . time() . " > 1800"); 83 | } 84 | 85 | public function dump($where = '') 86 | { 87 | /* cant check such thing, so trust :) */ 88 | if ($where) { 89 | $where = "WHERE $where"; 90 | } 91 | 92 | $res = $this->query("SELECT * FROM ext_release $where ORDER BY ext_name, ext_version ASC"); 93 | echo "DUMP ext_release " . PHP_EOL . PHP_EOL; 94 | while(false !== ($row = $res->fetchArray(SQLITE3_ASSOC))) { 95 | foreach ($row as $col => $val) { 96 | echo "$col=$val" . PHP_EOL; 97 | } 98 | echo PHP_EOL; 99 | } 100 | $res->finalize(); 101 | } 102 | 103 | public function dumpQueue() 104 | { 105 | $this->dump("ts_built <= 0"); 106 | } 107 | 108 | public function touch($name, $version) 109 | { 110 | $name = $this->escapeString($name); 111 | $version = $this->escapeString($version); 112 | $sql = "UPDATE ext_release SET ts_built=" . time() . " WHERE lower(ext_name) = lower('$name') AND lower(ext_version) = lower('$version');"; 113 | $this->exec($sql); 114 | } 115 | } 116 | 117 | -------------------------------------------------------------------------------- /include/PeclMail.php: -------------------------------------------------------------------------------- 1 | array(), 11 | 'to' => array(), 12 | 'subject' => '', 13 | 'text' => '', 14 | 'attachment' => array() 15 | ); 16 | 17 | public function __construct($pkg_path, $aggregate = false) 18 | { 19 | if (!file_exists($pkg_path)) { 20 | throw new \Exception("'$pkg_path' does not exist"); 21 | } 22 | 23 | $this->buffer_file = TMP_DIR . DIRECTORY_SEPARATOR . md5($pkg_path); 24 | $this->aggregate = (boolean)$aggregate; 25 | 26 | if ($this->aggregate && file_exists($this->buffer_file)) { 27 | $tmp = file_get_contents($this->buffer_file); 28 | $this->buffer = unserialize($tmp); 29 | } 30 | } 31 | 32 | public function saveState() 33 | { 34 | $tmp = serialize($this->buffer); 35 | $ret = file_put_contents($this->buffer_file, $tmp); 36 | } 37 | 38 | public function cleanup() 39 | { 40 | unlink($this->buffer_file); 41 | } 42 | 43 | public function isAggregated() 44 | { 45 | return $this->aggregate; 46 | } 47 | 48 | /* XXX the state with from, to and subject is somehow unclean */ 49 | public function xmail($from, $to, $subject, $text, array $attachment = array()) 50 | { 51 | if (!$this->aggregate) { 52 | return xmail($from, $to, $subject, $text, $attachment); 53 | } 54 | 55 | /* aggregate all the stuff below */ 56 | $this->buffer['to'][] = $to; 57 | $this->buffer['from'][] = $from; 58 | /* subject can't be aggregated anyway , or?*/ 59 | $this->buffer['subject'] = $subject; 60 | $this->buffer['text'] = $this->buffer['text'] ."\n" . $text; 61 | $this->buffer['attachment'] = array_merge($attachment, $this->buffer['attachment']); 62 | 63 | $this->saveState(); 64 | 65 | /* fake we've sent it */ 66 | return true; 67 | } 68 | 69 | public function mailAggregated($from, $to, $subject, $open, $close, $with_attachment) 70 | { 71 | if (!$to) { 72 | $to = implode(',', array_unique($this->buffer['to'])); 73 | } 74 | if (!$from) { 75 | $from = implode(',', array_unique($this->buffer['from'])); 76 | } 77 | $text = "$open\n\n" . $this->buffer['text'] . "\n\n$close"; 78 | 79 | $attachment = $with_attachment ? $this->buffer['attachment'] : array(); 80 | 81 | $this->aggregated_sent = true; 82 | 83 | return xmail($from, $to, $subject, $text, $attachment); 84 | } 85 | 86 | public function setFrom($from) 87 | { 88 | $this->buffer['from'] = $from; 89 | } 90 | 91 | public function setTo($to) 92 | { 93 | $this->buffer['to'] = $to; 94 | } 95 | 96 | public function setSubject($subject) 97 | { 98 | $this->buffer['subject'] = $subject; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /include/Pickle.php: -------------------------------------------------------------------------------- 1 | pickle_phar = $pickle; 14 | } 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /include/PickleBranch.php: -------------------------------------------------------------------------------- 1 | '); 15 | } 16 | $this->config = new BranchConfig($config_path); 17 | $this->addBuildList(); 18 | } 19 | 20 | private function addBuildList() 21 | { 22 | $builds = $this->config->getBuildList(); 23 | 24 | if (!empty($builds)) { 25 | $this->builds = array(); 26 | foreach ($builds as $n => $v) { 27 | $this->builds[] = $n; 28 | } 29 | } else { 30 | $this->builds = NULL; 31 | } 32 | } 33 | 34 | public function update() 35 | { 36 | // pass 37 | } 38 | 39 | public function hasNewRevision() 40 | { 41 | return false; 42 | } 43 | 44 | public function export($revision = false, $build_type = false, $zip = false, $is_zip = false) 45 | { 46 | // TODO 47 | } 48 | 49 | public function createSourceSnap($build_type = false, $revision = false) 50 | { 51 | return $this->export($revision, $build_type, true); 52 | } 53 | 54 | public function setLastRevisionExported($last_rev) 55 | { 56 | // pass 57 | } 58 | 59 | public function getLastRevisionExported() 60 | { 61 | return NULL; 62 | } 63 | 64 | public function getLastRevisionId() 65 | { 66 | return NULL; 67 | } 68 | 69 | public function getPreviousRevision() 70 | { 71 | return NULL; 72 | } 73 | 74 | function getBuildList($platform) 75 | { 76 | $builds = array(); 77 | foreach ($this->builds as $build_name) { 78 | $build = $this->config->getBuildFromName($build_name); 79 | if (isset($build['platform']) && $build['platform'] == $platform) { 80 | $builds[] = $build_name; 81 | } 82 | } 83 | return $builds; 84 | } 85 | 86 | function createBuildInstance($build_name) 87 | { 88 | $build = NULL; 89 | $build_config = $this->config->getBuildFromName($build_name); 90 | 91 | if (!$build_config) { 92 | throw new \Exception("Invalid build name <$build_name>"); 93 | } 94 | 95 | $compiler = strtolower($build_config['compiler']); 96 | switch ($compiler) { 97 | case 'vc14': 98 | case 'vc12': 99 | case 'vc11': 100 | case 'vc9': 101 | case 'vc6': 102 | $build = new PickleBuildVC($this, $build_name); 103 | break; 104 | case 'icc': 105 | case 'gcc': 106 | case 'clang': 107 | throw new \Exception("$compiler not supported yet. Not implemented"); 108 | break; 109 | } 110 | 111 | return $build; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /include/PickleBuildVC.php: -------------------------------------------------------------------------------- 1 | branch = $branch; 27 | $this->build_name = $build_name; 28 | 29 | $this->int_dir = tempnam(TMP_DIR, 'pickle'); 30 | unlink($this->int_dir); 31 | if (!file_exists($this->int_dir) && !mkdir($this->int_dir)) { 32 | throw new \Exception("Couldn't create temporary dir"); 33 | } 34 | 35 | $this->log_dir = $this->int_dir . DIRECTORY_SEPARATOR . "pickle_logs"; 36 | if (!mkdir($this->log_dir)) { 37 | throw new \Exception("Couldn't create log dir"); 38 | } 39 | 40 | /* Use --no-ansi for now for better parsing if needed. Should tweak pickle to support --xml/--json */ 41 | $this->pickle_cmd = PHP_BINARY . " " . $this->pickle_phar . " --no-ansi "; 42 | 43 | 44 | $this->compiler = $branch->config->builds[$build_name]['compiler']; 45 | $this->architecture = $branch->config->builds[$build_name]['arch']; 46 | $this->thread_safe = (boolean)$branch->config->builds[$build_name]['thread_safe']; 47 | $this->pecl_deps_base = $branch->config->builds[$build_name]['pecl_deps_base']; 48 | if (!file_exists($this->pecl_deps_base)) { 49 | throw new \Exception("Dependency libs not found under '{$this->pecl_deps_base}'"); 50 | } 51 | $this->core_deps_base = $branch->config->builds[$build_name]['core_deps_base']; 52 | if (!file_exists($this->core_deps_base)) { 53 | throw new \Exception("Dependency libs not found under '{$this->core_deps_base}'"); 54 | } 55 | 56 | 57 | $vc_env_prefix = strtoupper($this->compiler); 58 | if ($this->architecture == 'x64') { 59 | $vc_env_prefix .= '_X64_'; 60 | } else { 61 | $vc_env_prefix .= '_'; 62 | } 63 | 64 | $path = getenv($vc_env_prefix . 'PATH'); 65 | if (empty($path)) { 66 | include __DIR__ . '/../data/config.php'; 67 | /* use default config */ 68 | $env = $custom_env; 69 | } else { 70 | $env = array(); 71 | $env['PATH'] = getenv($vc_env_prefix . 'PATH') . ';' . getenv('PATH') ; 72 | $env['INCLUDE'] = getenv($vc_env_prefix . 'INCLUDE'); 73 | $env['LIB'] = getenv($vc_env_prefix . 'LIB'); 74 | } 75 | 76 | if (!$env['INCLUDE'] || !$env['LIB']) { 77 | $env['INCLUDE'] = getenv('INCLUDE'); 78 | $env['LIB'] = getenv('LIB'); 79 | } 80 | 81 | 82 | $env['TMP'] = $env['TEMP'] = getenv('TEMP'); 83 | $env['SystemDrive'] = getenv('SystemDrive'); 84 | $env['SystemRoot'] = getenv('SystemRoot'); 85 | if (!isset($env['BISON_SIMPLE'])) { 86 | $env['BISON_SIMPLE'] = getenv('BISON_SIMPLE'); 87 | } 88 | 89 | $env['CPU'] = "i386"; 90 | $env['APPVER'] = "6.0"; 91 | if ($branch->config->getDebug() == 0) { 92 | $env['NODEBUG'] = "1"; 93 | } 94 | if (strcasecmp($this->architecture, 'x64') == 0) { 95 | $env['CPU'] = "AMD64"; 96 | } 97 | 98 | $this->sdk_path = $branch->config->getBuildFromName($build_name)["sdk_path"]; 99 | $env["PATH"] = "{$this->sdk_path};" . $env["PATH"]; 100 | 101 | $env["PATH"] = "c:\\apps\\git\\bin;c:\\apps\\bin;" . $env["PATH"]; 102 | 103 | $this->env = $env; 104 | } 105 | 106 | public function __destruct() 107 | { 108 | $this->clean(); 109 | } 110 | 111 | public function getPickleCmd() 112 | { 113 | return $this->pickle_cmd; 114 | } 115 | 116 | public function setSdkDir($sdk_dir) 117 | { 118 | $this->sdk_dir = $sdk_dir; 119 | } 120 | 121 | function clean() 122 | { 123 | if (is_dir($this->int_dir)) { 124 | /* XXX something seems to be missing in unlink(), .git has some ACLs so then 125 | PHP cannot handle the removal of the several items in it. Using the 126 | system commando helps with that. */ 127 | $items = scandir($this->int_dir); 128 | foreach ($items as $item) { 129 | $dir = "{$this->int_dir}/$item"; 130 | 131 | if (is_dir("$dir/.git")) { 132 | @shell_exec("del /F /S /Q /A " . realpath($dir) . DIRECTORY_SEPARATOR . ".git"); 133 | } 134 | } 135 | 136 | rmdir_rf($this->int_dir); 137 | } 138 | } 139 | 140 | public function info() 141 | { 142 | 143 | } 144 | 145 | public function getPickleCmdToRun(PickleExt $ext) 146 | { 147 | $conf_opts = $ext->getConfigureOpts(); 148 | if ($conf_opts && file_exists($conf_opts)) { 149 | $ext_config_opt = "--with-configure-options=$conf_opts"; 150 | } else { 151 | $ext_config_opt = "--defaults"; 152 | } 153 | 154 | /* XXX check if --quiet needed */ 155 | $opts = " --binary " 156 | . " $ext_config_opt " 157 | . "--tmp-dir={$this->int_dir} " 158 | . "--pack-logs " 159 | . "release " 160 | . $ext->getPkgUri(); 161 | 162 | $cmd = $this->pickle_cmd . " " . $opts; 163 | 164 | return $cmd; 165 | 166 | } 167 | 168 | 169 | /* XXX read the configure options from the extconfig, create the options file to feed pickle */ 170 | public function build(PickleExt $ext) 171 | { 172 | $old_cwd = getcwd(); 173 | 174 | chdir(TMP_DIR); 175 | 176 | $cmd = $this->getPickleCmdToRun($ext); 177 | 178 | $ret = exec_single_log($cmd, NULL, $this->env); 179 | 180 | $ext->cleanConfigureOpts(); 181 | 182 | chdir($old_cwd); 183 | 184 | return $ret; 185 | } 186 | 187 | public function archive() 188 | { 189 | 190 | } 191 | 192 | public function getIntDir() 193 | { 194 | return $this->int_dir; 195 | } 196 | 197 | public function getEnv() 198 | { 199 | return $this->env; 200 | } 201 | } 202 | 203 | -------------------------------------------------------------------------------- /include/PickleDb.php: -------------------------------------------------------------------------------- 1 | db_path = $this->createDir($db_path); 12 | } 13 | 14 | protected function isSlash($c) 15 | { 16 | return '\\' == $c || '/' == $c; 17 | } 18 | 19 | 20 | protected function buildUriLocalPath($uri) 21 | { 22 | if (!$this->isSlash($uri[0])) { 23 | $uri = DIRECTORY_SEPARATOR . $uri; 24 | } 25 | $uri = str_replace('/', DIRECTORY_SEPARATOR, $uri); 26 | 27 | return $this->db_path . $uri; 28 | } 29 | 30 | public function uriExists($uri) 31 | { 32 | return file_exists($this->buildUriLocalPath($uri)); 33 | } 34 | 35 | public function getUri($uri) 36 | { 37 | $fname = $this->buildUriLocalPath($uri); 38 | 39 | if (!file_exists($fname)) { 40 | return false; 41 | } 42 | 43 | return file_get_contents($fname); 44 | } 45 | 46 | public function saveUriJson($uri, $data) 47 | { 48 | $json = json_encode($data, JSON_PRETTY_PRINT); 49 | 50 | return $this->saveUri($uri, $json); 51 | } 52 | 53 | public function saveUri($uri, $data) 54 | { 55 | $fname = $this->buildUriLocalPath($uri); 56 | 57 | $dir = dirname($fname); 58 | if (!is_dir($dir)) { 59 | $this->createDir($dir); 60 | } 61 | 62 | return strlen($data) == file_put_contents($fname, $data, LOCK_EX); 63 | } 64 | 65 | public function getUriJson($uri) 66 | { 67 | return json_decode($this->getUri($uri), true); 68 | } 69 | 70 | public function delUri($uri) 71 | { 72 | $fname = $this->buildUriLocalPath($uri); 73 | 74 | if (!file_exists($fname)) { 75 | return true; 76 | } 77 | 78 | return unlink($fname); 79 | } 80 | 81 | protected function createDir($path, $rec = true) 82 | { 83 | if (!is_dir($path)) { 84 | if (!mkdir($path, 0777, $rec)) { 85 | throw new \Exception("failed to create '$path'"); 86 | } 87 | } 88 | 89 | return realpath($path); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /include/PickleExt.php: -------------------------------------------------------------------------------- 1 | pkg_uri = $pkg_uri; 24 | $this->build = $build; 25 | } 26 | 27 | 28 | public function init() 29 | { 30 | $this->pickle_cmd = $this->build->getPickleCmd(); 31 | 32 | 33 | $cmd = "{$this->pickle_cmd} info {$this->pkg_uri}"; 34 | $ret = exec_single_log($cmd, NULL, $this->build->getEnv()); 35 | 36 | if ($ret["return_value"]) { 37 | throw new \Exception("'$cmd' resulted error: '" . $ret["log"] . "'"); 38 | } 39 | 40 | if (!preg_match(",Package name\s+\|\s+([^\s]+)\s+\|,", $ret["log"], $m)) { 41 | throw new \Exception("Couldn't parse extension name"); 42 | } 43 | $this->setupNames($m[1]); 44 | 45 | if (!preg_match(",Package version.+\|\s+([a-z0-9\.\-]+)\s+\|,i", $ret["log"], $m)) { 46 | throw new \Exception("Couldn't parse extension version"); 47 | } 48 | $this->version = $m[1]; 49 | } 50 | 51 | public function getName() 52 | { 53 | return $this->name; 54 | } 55 | 56 | public function getVendor() 57 | { 58 | return $this->vendor; 59 | } 60 | 61 | public function getVersion() 62 | { 63 | return $this->version; 64 | } 65 | 66 | public function preparePackage() 67 | { 68 | 69 | } 70 | 71 | public function check() 72 | { 73 | 74 | } 75 | 76 | protected function createTmpDir() 77 | { 78 | $tmp_path = tempnam(TMP_DIR, 'pickle'); 79 | unlink($tmp_path); 80 | if (!file_exists($tmp_path) && !mkdir($tmp_path)) { 81 | throw new \Exception("Couldn't create temporary dir"); 82 | } 83 | 84 | return $tmp_path; 85 | } 86 | 87 | public function getPkgUri() 88 | { 89 | return $this->pkg_uri; 90 | } 91 | 92 | public function cleanup() 93 | { 94 | $this->cleanConfigureOpts(); 95 | } 96 | 97 | protected function complexPkgNameMatch($cnf_name) { 98 | $full_set = array( 99 | $this->build->branch->config->getBranch(), 100 | ($this->build->thread_safe ? 'ts' : 'nts'), 101 | $this->build->compiler, 102 | $this->build->architecture, 103 | ); 104 | 105 | if (!function_exists('rmtools\combinations')) { 106 | function combinations($arr, $level, &$result, $that, $curr=array()) { 107 | for($i = 0; $i < count($arr); $i++) { 108 | $new = array_merge($curr, array($arr[$i])); 109 | if($level == 1) { 110 | /* preserve order */ 111 | sort($new); 112 | /* no repititions */ 113 | $new = array_unique($new); 114 | $name = $that->getName() . '-' . implode('-', $new); 115 | if (!in_array($name, $result)) { 116 | $result[] = $name; 117 | } 118 | } else { 119 | combinations($arr, $level - 1, $result, $that, $new); 120 | } 121 | } 122 | } 123 | } 124 | 125 | $names = array(); 126 | for ($i = 0; $ipkg_config) { 144 | return $this->pkg_config; 145 | } 146 | 147 | $known_path = __DIR__ . '/../data/config/pickle/exts.ini'; 148 | $exts = parse_ini_file($known_path, true, INI_SCANNER_RAW); 149 | 150 | /* Check for like myext-5.3-ts-vc9-x86 */ 151 | foreach ($exts as $name => $conf) { 152 | if ($this->complexPkgNameMatch($name)) { 153 | $config = $conf; 154 | break; 155 | } 156 | } 157 | 158 | /* XXX this here might be redundant */ 159 | if (!$config) { 160 | foreach ($exts as $name => $conf) { 161 | if ($name === $this->name) { 162 | $config = $conf; 163 | break; 164 | } 165 | } 166 | } 167 | 168 | $this->pkg_config = $config; 169 | 170 | return $config; 171 | } 172 | 173 | /* ignore me */ 174 | public function sendToCoventry() 175 | { 176 | $config = $this->getPackageConfig(); 177 | 178 | return $config && isset($config['ignore']); 179 | } 180 | 181 | /* Depending on other extensions is neither handled nor supported by phpize. 182 | This will need significant change in the PHP build, but still doable. 183 | Or, it'll need some quite tricky business inside rmtools, still doable 184 | as well. */ 185 | public function getConfigureOpts() 186 | { 187 | $config = $this->getPackageConfig(); 188 | 189 | /* Ext isn't known, force pickle --defaults */ 190 | if (!$config) { 191 | return NULL; 192 | } 193 | 194 | $conf = $this->buildConfigureLine($config); 195 | $conf .= " --enable-debug-pack"; 196 | 197 | $fn = $this->build->getIntDir() . DIRECTORY_SEPARATOR . $this->getName() . ".conf"; 198 | if (strlen($conf) != file_put_contents($fn, $conf)) { 199 | throw new \Exception("Error writing build config into '$fn'"); 200 | } 201 | 202 | $this->conf_opts = $fn; 203 | return $this->conf_opts; 204 | } 205 | 206 | public function cleanConfigureOpts() 207 | { 208 | if (file_exists($this->conf_opts)) { 209 | unlink($this->conf_opts); 210 | } 211 | } 212 | 213 | protected function buildConfigureLine(array $data) 214 | { 215 | $ret = ''; 216 | $ignore_main_opt = false; 217 | 218 | if (!isset($data['type']) 219 | || !in_array($data['type'], array('with', 'enable'))) { 220 | throw new \Exception("Unknown extention configure type, expected enable/with"); 221 | } 222 | 223 | $main_opt = '--' . $data['type'] . '-' . str_replace('_', '-', $this->name); 224 | 225 | if (isset($data['opts']) && $data['opts']) { 226 | $data['opts'] = !is_array($data['opts']) ? array($data['opts']) : $data['opts']; 227 | foreach($data['opts'] as $opt) { 228 | if ($opt) { 229 | /* XXX simple check for opt syntax */ 230 | $ret .= ' "' . $opt . '" '; 231 | } 232 | /* the main enable/with option was overridden in the ini */ 233 | if (strstr($opt, "$main_opt=") !== false) { 234 | $ignore_main_opt = true; 235 | } 236 | } 237 | } else { 238 | $data['opts'] = array(); 239 | } 240 | 241 | $ignore_main_opt = $ignore_main_opt || isset($data['no_conf']); 242 | 243 | if (!$ignore_main_opt) { 244 | $ret .= ' "' . $main_opt . '=shared" '; 245 | } 246 | 247 | /* XXX this defines the core libraries as extra, maybe there's a better way. */ 248 | $extra_lib = array($this->build->core_deps_base . DIRECTORY_SEPARATOR . "lib"); 249 | $extra_inc = array($this->build->core_deps_base . DIRECTORY_SEPARATOR . "include"); 250 | 251 | if (isset($data['libs']) && $data['libs']) { 252 | $data['libs'] = !is_array($data['libs']) ? array($data['libs']) : $data['libs']; 253 | $deps_path = $this->build->pecl_deps_base; 254 | 255 | foreach($data['libs'] as $lib) { 256 | if (!$lib) { 257 | continue; 258 | } 259 | 260 | $lib_conf = $this->getLibraryConfig($lib); 261 | 262 | $lib_path = $deps_path . DIRECTORY_SEPARATOR . $lib; 263 | 264 | $some_lib_path = $lib_path . DIRECTORY_SEPARATOR . 'lib'; 265 | if (!file_exists($some_lib_path)) { 266 | throw new \Exception("Path '$some_lib_path' doesn't exist"); 267 | } 268 | $extra_lib[] = $some_lib_path; 269 | 270 | $some_lib_inc_path = $lib_path . DIRECTORY_SEPARATOR . 'include'; 271 | if (!file_exists($some_lib_inc_path)) { 272 | throw new \Exception("Path '$some_lib_inc_path' doesn't exist"); 273 | } 274 | $extra_inc[] = $some_lib_inc_path; 275 | 276 | /* If expand_include not set, consider true. */ 277 | if (!isset($lib_conf['expand_include']) || $lib_conf['expand_include']) { 278 | $dirs = glob("$some_lib_inc_path/*", GLOB_ONLYDIR); 279 | foreach ($dirs as $dir) { 280 | $extra_inc[] = $dir; 281 | } 282 | } 283 | } 284 | } else { 285 | $data['libs'] = array(); 286 | } 287 | 288 | $ret .= ' "--with-extra-libs=' . implode(';', $extra_lib) . '" ' 289 | . ' "--with-extra-includes=' . implode(';', $extra_inc) . '" '; 290 | 291 | $this->configure_data = $data; 292 | 293 | return $ret; 294 | } 295 | 296 | public function getLibraryConfig($name) 297 | { 298 | $ret = array(); 299 | 300 | $known_path = __DIR__ . '/../data/config/pickle/libs.ini'; 301 | $lib_conf = parse_ini_file($known_path, true, INI_SCANNER_RAW); 302 | 303 | if (isset($lib_conf[$name]) && is_array($lib_conf[$name])) { 304 | $ret = $lib_conf[$name]; 305 | } 306 | 307 | return $ret; 308 | } 309 | 310 | protected function setupNames($full_name) 311 | { 312 | if (preg_match(",(.+)/(.+),", $full_name, $m)) { 313 | $this->name = $m[2]; 314 | $this->vendor = $m[1]; 315 | } else { 316 | throw new \Exception("Couldn't parse vendor from '$full_name'"); 317 | } 318 | } 319 | } 320 | 321 | -------------------------------------------------------------------------------- /include/PickleJob.php: -------------------------------------------------------------------------------- 1 | job_dir = $job_dir; 17 | } 18 | 19 | public static function loadData($path) 20 | { 21 | if (!file_exists($path)) { 22 | throw new \Exception("Couldn't load job file '$path'"); 23 | } 24 | 25 | $job_data = json_decode(file_get_contents($path), true); 26 | if (!$job_data) { 27 | throw new \Exception("Couldn't decode job data from '$path'"); 28 | } 29 | 30 | return $job_data; 31 | } 32 | 33 | public function add(array $tag) 34 | { 35 | if (!isset($tag["source"]["url"])) { 36 | throw new \Exception("Tag source location isn't set, no job created for '$tag[name]-$tag[version]'"); 37 | } 38 | 39 | $data = array( 40 | "name" => $tag["name"], 41 | "version" => $tag["version"], 42 | "src" => $tag["source"]["url"] . "#" . $tag["version"], 43 | "status" => "new", 44 | ); 45 | 46 | $tmp = tempnam($this->job_dir, $tag["name"]); 47 | if (false === $tmp) { 48 | throw new \Exception("Failed to create temporary job file"); 49 | } 50 | 51 | $fn = "$tmp.job"; 52 | 53 | if (!rename($tmp, $fn)) { 54 | throw new \Exception("Failed to create job file"); 55 | } 56 | 57 | $this->save($fn, $data); 58 | } 59 | 60 | protected function save($fn, $data) 61 | { 62 | $json = json_encode($data, JSON_PRETTY_PRINT); 63 | 64 | if (strlen($json) != file_put_contents($fn, $json, LOCK_EX)) { 65 | throw new \Exception("Error while writing data to '$fn'"); 66 | } 67 | } 68 | 69 | protected function validStatus($st) 70 | { 71 | return "new" == $st || 72 | "fail" == $st || 73 | "pass" == $st; 74 | } 75 | 76 | public function setStatus($sha, $status) 77 | { 78 | $fn = "{$this->job_dir}/$sha.job"; 79 | 80 | if (!$this->validStatus($status)) { 81 | throw new \Exception("Invalid job status '$status'"); 82 | } 83 | 84 | if (!file_exists($fn)) { 85 | throw new \Exception("Job '$fn' doesn't exist"); 86 | } 87 | 88 | $data = json_decode(file_get_contents($fn), true); 89 | 90 | $data["status"] = $status; 91 | 92 | $this->save($fn, $data); 93 | } 94 | 95 | public function getNextNew() 96 | { 97 | $jobs = glob("{$this->job_dir}/*.job"); 98 | 99 | foreach ($jobs as $fn) { 100 | $data = json_decode(file_get_contents($fn), true); 101 | if ("new" == $data["status"]) { 102 | return $data; 103 | } 104 | } 105 | 106 | return NULL; 107 | } 108 | 109 | public function cleanup() 110 | { 111 | $jobs = glob("{$this->job_dir}/*.job"); 112 | 113 | foreach ($jobs as $fn) { 114 | $data = json_decode(file_get_contents($fn), true); 115 | if ("fail " == $data["status"] || "fail " == $data["status"]) { 116 | /* XXX save this to PickleDB */ 117 | unlink($fn); 118 | } 119 | } 120 | } 121 | } 122 | 123 | -------------------------------------------------------------------------------- /include/PickleWeb.php: -------------------------------------------------------------------------------- 1 | host = $host; 17 | $this->db = $db; 18 | 19 | $this->init(); 20 | } 21 | 22 | protected function fetchUri($uri, $allow_empty = false) 23 | { 24 | 25 | $url = "{$this->host}$uri"; 26 | 27 | $__tmp = file_get_contents($url); 28 | 29 | 30 | if (false === $__tmp) { 31 | throw new \Exception("Error encountered while receiving '$url'"); 32 | } 33 | 34 | if (!$allow_empty && !$__tmp) { 35 | throw new \Exception("Empty content received from '$url'"); 36 | } 37 | 38 | return $__tmp; 39 | } 40 | 41 | protected function fetchUriJson($uri, $allow_empty = false) 42 | { 43 | $__tmp = $this->fetchUri($uri, $allow_empty); 44 | 45 | $ret = json_decode($__tmp, true); 46 | if (!$ret) { 47 | throw new \Exception("Couldn't decode JSON from '$uri' on '{$this->host}'"); 48 | } 49 | 50 | return $ret; 51 | } 52 | 53 | public function init() 54 | { 55 | $uri = "/packages.json"; 56 | $this->info = $this->fetchUriJson($uri); 57 | 58 | if (!isset($this->info["provider-includes"])) { 59 | throw new \Exception("No provider includes found"); 60 | } 61 | 62 | $this->db->delUri($uri); /* XXX pure dev stuff, remove in prod */ 63 | if (!$this->db->uriExists($uri)) { 64 | $this->updatesAvailableFlag = true; 65 | } else { 66 | $packages_info = $this->db->getUriJson($uri); 67 | foreach ($this->info["provider-includes"] as $provider_uri => $hash) { 68 | if (!isset($packages_info["provider-includes"][$provider_uri]) || 69 | $packages_info["provider-includes"][$provider_uri] != $hash) { 70 | $this->updatesAvailableFlag = true; 71 | break; 72 | } 73 | } 74 | } 75 | if ($this->updatesAvailableFlag && !$this->db->saveUriJson($uri, $this->info)) { 76 | throw new \Exception("Couldn't save '$uri'"); 77 | } 78 | } 79 | 80 | public function updatesAvailable() 81 | { 82 | return $this->updatesAvailableFlag; 83 | } 84 | 85 | 86 | protected function saveUriLocal($uri) 87 | { 88 | 89 | } 90 | 91 | protected function getUriLocal($uri) 92 | { 93 | 94 | } 95 | 96 | 97 | protected function diffProviders(array $remote, array $local) 98 | { 99 | $ret = array(); 100 | 101 | if (!isset($remote["providers"]) || !is_array($remote["providers"]) || empty($remote["providers"])) { 102 | return array(); 103 | } else if (!isset($llocal["providers"]) || !is_array($local["providers"]) || empty($local["providers"])) { 104 | return $remote["providers"]; 105 | } 106 | 107 | foreach ($remote as $vendor => $sha) { 108 | if (isset($local[$vendor]) && $local[$vendor] != $sha) { 109 | $ret[$vendor] = $sha; 110 | } 111 | } 112 | 113 | return $ret; 114 | } 115 | 116 | public function fetchProviderUpdates() 117 | { 118 | $ret = array(); 119 | 120 | foreach ($this->info["provider-includes"] as $uri => $hash) { 121 | $pkgs_new = (array)$this->fetchUriJson($uri); 122 | $pkgs = (array)$this->db->getUriJson($uri); 123 | 124 | if (!$this->db->saveUriJson($uri, $pkgs_new)) { 125 | throw new \Exception("Failed to save '$uri'"); 126 | } 127 | 128 | $ret = array_merge($ret, $this->diffProviders($pkgs_new, $pkgs)); 129 | } 130 | 131 | return $ret; 132 | } 133 | 134 | protected function isUniqueTag($name, $version, array $tags) 135 | { 136 | foreach ($tags as $tag) { 137 | if ($tag["name"] == $name && $tag["version"] == $version) { 138 | return false; 139 | } 140 | } 141 | 142 | return true; 143 | } 144 | 145 | protected function isValidTag(array $tag) 146 | { 147 | /* XXX raise some errors on this, or be more verbose at least ??? */ 148 | return isset($tag["name"]) && 149 | !empty($tag["name"]) && 150 | isset($tag["version"]) && 151 | !empty($tag["version"]) && 152 | isset($tag["source"]["url"]) && 153 | !empty($tag["source"]["url"]) /* XXX might check at least the URL format */; 154 | } 155 | 156 | public function diffTags(array $remote, array $local) 157 | { 158 | $ret = array(); 159 | 160 | if (empty($remote) || !isset($remote["packages"])) { 161 | return array(); 162 | } else if (empty($local) || !isset($local["packages"])) { 163 | foreach ($remote["packages"] as $name => $tags) { 164 | foreach ($tags as $version => $data) { 165 | /*if (!$this->isValidTag($data)) { 166 | continue; 167 | }*/ 168 | /* $version is from the tag name, be strict and use the oone from the actual tag data*/ 169 | if ($this->isUniqueTag($name, $data["version"], $ret)) { 170 | $ret[] = $data; 171 | } 172 | } 173 | } 174 | 175 | return $ret; 176 | } 177 | 178 | foreach ($remote["packages"] as $name => $tags) { 179 | if (!isset($local["packages"][$name])) { 180 | $ret[$name] = $data; 181 | break; 182 | } 183 | 184 | foreach ($tags as $version => $data) { 185 | /*if (!$this->isValidTag($data)) { 186 | continue; 187 | }*/ 188 | if (!isset($local["packages"][$name][$version]) && $this->isUniqueTag($name, $data["version"], $ret)) { 189 | $ret[] = $data; 190 | } 191 | } 192 | } 193 | 194 | return $ret; 195 | } 196 | 197 | public function getNewTags() 198 | { 199 | $provs = $this->fetchProviderUpdates(); 200 | $ret = array(); 201 | 202 | /* $name the ext name is, vendor/foo it looks like */ 203 | foreach ($provs as $name => $sha) { 204 | $uri = "/json/$name.json"; 205 | 206 | $remote = (array)$this->fetchUriJson($uri); 207 | $local = (array)$this->db->getUriJson($uri); 208 | 209 | if (!$this->db->saveUriJson($uri, $remote)) { 210 | throw new \Exception("Failed to save '$uri'"); 211 | } 212 | 213 | $ret = array_merge($ret, $this->diffTags($remote, $local)); 214 | } 215 | 216 | return $ret; 217 | } 218 | 219 | public function pingBack($data) 220 | { 221 | // TODO send the build data to pickle web 222 | } 223 | 224 | } 225 | 226 | -------------------------------------------------------------------------------- /include/Repository.php: -------------------------------------------------------------------------------- 1 | getRepoName(); 12 | $config_path = __DIR__ . '/../data/config/repo/' . $name . '.ini'; 13 | 14 | if (!is_readable($config_path)) { 15 | throw new \Exception('Cannot open repo data <' . $config_path . '>'); 16 | } 17 | 18 | $repo = parse_ini_file($config_path, true,INI_SCANNER_RAW); 19 | if (!$repo) { 20 | throw new \Exception('Cannot parse config file <' . $config_path . '>'); 21 | } 22 | 23 | if (!isset($repo['type'])) { 24 | throw new \Exception('Invalid repo config data, no type defined'); 25 | } 26 | switch ($repo['type']) { 27 | case 'svn': 28 | $r = new Svn($repo['url']); 29 | return $r; 30 | break; 31 | case 'git': 32 | $r = new Git($repo['url'], isset($repo['gh_url']) ? $repo['gh_url'] : null); 33 | return $r; 34 | break; 35 | default: 36 | throw new \Exception('Invalid repo config data, invalid type defined'); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /include/Svn.php: -------------------------------------------------------------------------------- 1 | repo_url = $repo_url; 13 | } 14 | 15 | function setModule($module) { 16 | $this->module = $module; 17 | } 18 | 19 | function setBranch($branch) { 20 | $this->branch = $branch; 21 | } 22 | 23 | public function export($dest, $revision = false) 24 | { 25 | $cmd = $this->svn_cmd . ' export -q ' . $this->repo_url . $this->module. $this->branch . ' ' . $dest; 26 | $res = exec_single_log($cmd); 27 | if ($res === FALSE) { 28 | throw new \Exception('svn export failed <' . $this->repo_url . '/' . $this->module. '/' . $this->branch . '>'); 29 | } 30 | } 31 | 32 | public function info() 33 | { 34 | } 35 | 36 | public function getLastCommitId() 37 | { 38 | $path = $this->repo_url . $this->module. $this->branch; 39 | $cmd = $this->svn_cmd . ' info --xml ' . $path; 40 | 41 | $res = exec_sep_log($cmd); 42 | if ($res && is_null($res['log_stdout'])) { 43 | throw new \Exception('svn log failed <' . $this->repo_url . '/' . $this->module. '/' . $this->branch . '>'); 44 | } 45 | 46 | $sx = new \SimpleXMLElement($res['log_stdout']); 47 | if (!$sx) { 48 | throw new \Exception('svn log failed ' . $path); 49 | } 50 | $revision = (int)($sx->entry->commit['revision']); 51 | return $revision; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /locks/.dummy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/web-rmtools/68e1116d4740c32d21791e122683a8589748e3e4/locks/.dummy -------------------------------------------------------------------------------- /logs/.dummy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/web-rmtools/68e1116d4740c32d21791e122683a8589748e3e4/logs/.dummy -------------------------------------------------------------------------------- /script/pecl_rss.php: -------------------------------------------------------------------------------- 1 | dumpQueue(); 50 | exit(0); 51 | } 52 | 53 | /* --dump-all */ 54 | if ($dump_all) { 55 | $db->dump(); 56 | exit(0); 57 | } 58 | 59 | /* --refresh, need to wrap it all with ifs maybe*/ 60 | echo "Refreshing the data" . PHP_EOL; 61 | 62 | $rss = 'https://pecl.php.net/feeds/latest.rss'; 63 | 64 | echo "Fetching $rss" . PHP_EOL; 65 | $latest = simplexml_load_file($rss); 66 | if (!isset($latest->item)) { 67 | echo "No items could be found in $rss" . PHP_EOL; 68 | } 69 | 70 | /* FIXME Use a separate config for this! */ 71 | $curl = 'C:\apps\bin\curl.exe'; 72 | $get_url_tpl = 'https://pecl.php.net/get/{name}/{version}'; 73 | $download_dir = 'c:\php-snap-build\in-pkg\release'; 74 | $download_dir_pre = 'c:\php-snap-build\in-pkg\snap-pre'; 75 | 76 | foreach($latest->item as $item) { 77 | if (!$item->title) { 78 | continue; 79 | } 80 | 81 | $tmp = explode(' ', (string)$item->title); 82 | $name = $tmp[0]; 83 | $version = $tmp[1]; 84 | 85 | if (!$name || !$version) { 86 | continue; 87 | } 88 | 89 | if (!$no_fetch) { 90 | $get_url = str_replace( 91 | array('{name}', '{version}'), 92 | array($name, $version), 93 | $get_url_tpl 94 | ); 95 | 96 | /* XXX -k is needed as the host is good known, but the download can fail on 97 | certain versions because of certs */ 98 | $curl_cmd = $curl . ' -s -L -J -O -k ' . $get_url; 99 | $back = getcwd(); 100 | 101 | chdir($download_dir); 102 | 103 | $suspects = glob(strtolower($name) . "-" . strtolower($version) . "*"); 104 | 105 | if ($force_fetch) { 106 | if ($db->exists($name, $version)) { 107 | echo "<$name-$version> forcing download" . PHP_EOL; 108 | } 109 | 110 | foreach ($suspects as $f) { 111 | if (file_exists($f)) { 112 | unlink($f); 113 | } 114 | } 115 | } else if ($db->done($name, $version)) { 116 | echo "<$name-$version> is already done" . PHP_EOL; 117 | continue; 118 | } else if ($db->exists($name, $version)) { 119 | /* XXX no check if file exists here, but should be */ 120 | echo "<$name-$version> is already in the queue" . PHP_EOL; 121 | continue; 122 | } 123 | 124 | if (!$suspects) { 125 | system($curl_cmd, $status); 126 | 127 | if ($enable_pre) { 128 | copy("$name-$version.tgz", "$download_dir_pre" . DIRECTORY_SEPARATOR . "$name-$version.tgz"); 129 | } 130 | 131 | if ($status) { 132 | echo "<$name-$version> download failed" . PHP_EOL; 133 | chdir($back); 134 | continue; 135 | } 136 | } 137 | 138 | chdir($back); 139 | } 140 | 141 | if (!$db->exists($name, $version) && $db->add($name, $version, $force_fetch)) { 142 | echo "<$name-$version> added to the queue" . PHP_EOL; 143 | } 144 | /* 145 | * when need more, look here (or /r) using name and version 146 | * $url = 'https://pecl.php.net/rest/p/'; 147 | */ 148 | } 149 | 150 | exit(0); 151 | -------------------------------------------------------------------------------- /script/pickle.php: -------------------------------------------------------------------------------- 1 | getMessage(); 51 | exit(3); 52 | } 53 | } 54 | 55 | 56 | $config_path = __DIR__ . '/../data/config/pickle/' . $branch_name . '.ini'; 57 | 58 | $branch = new rm\PickleBranch($config_path); 59 | 60 | $branch_name = $branch->config->getName(); 61 | $builds = $branch->getBuildList('windows'); 62 | 63 | 64 | //var_dump($pickle); 65 | //var_dump($branch_name); 66 | //var_dump($builds); 67 | 68 | $was_errors = false; 69 | 70 | echo "Using <$pkg_path>" . PHP_EOL . PHP_EOL; 71 | 72 | $upload_status = array(); 73 | 74 | foreach ($builds as $build_name) { 75 | 76 | $build_error = 0; 77 | 78 | echo "Starting build $build_name" . PHP_EOL; 79 | 80 | //$build_config = $branch->config->getBuildFromName($build_name); 81 | 82 | try { 83 | $build = $branch->createBuildInstance($build_name); 84 | $ext = new rm\PickleExt($pkg_path, $build); 85 | } catch (Exception $e) { 86 | echo 'Error: ' . $e->getMessage() . PHP_EOL; 87 | 88 | /* send error mail*/ 89 | 90 | continue; 91 | } 92 | 93 | try { 94 | $ext->init(); 95 | } catch (Exception $e) { 96 | echo 'Error: ' . $e->getMessage() . PHP_EOL; 97 | 98 | /* send error mail*/ 99 | 100 | continue; 101 | } 102 | 103 | echo "Starting pickle build" . PHP_EOL; 104 | 105 | try { 106 | $cmd = $build->getPickleCmdToRun($ext); 107 | echo "Pickle command is " . PHP_EOL . " $cmd" . PHP_EOL; 108 | 109 | $ret = $build->build($ext); 110 | } catch (Exception $e) { 111 | echo 'Error: ' . $e->getMessage() . PHP_EOL; 112 | 113 | $ret = array("return_value" => 1, "log" => ""); 114 | /* send error mail*/ 115 | 116 | $build_error++; 117 | } 118 | 119 | if ($ret["return_value"]) { 120 | 121 | $build->clean(); 122 | $ext->cleanup(); 123 | $was_errors = true; 124 | 125 | echo "Build failed" . PHP_EOL; 126 | echo $ret["log"]; 127 | 128 | $build_error++; 129 | } 130 | 131 | /* XXX check zipballs path before saying this */ 132 | echo "Pickle build successful" . PHP_EOL; 133 | 134 | // add the deps license to the pickle archive ... or should pickle do that? 135 | 136 | /* upload logs and builds */ 137 | 138 | $fl_base = "php_" . $ext->getName() . "-" . $ext->getVersion() . "-" . $build->branch->config->getBranch() . "-" . ($build->thread_safe ? "ts" : "nts") . "-" . $build->compiler . "-" . $build->architecture; 139 | 140 | $logs_zip = realpath(TMP_DIR . DIRECTORY_SEPARATOR . "$fl_base-logs.zip"); 141 | $pkg_file = realpath(TMP_DIR . DIRECTORY_SEPARATOR . "$fl_base.zip"); 142 | 143 | $upload_success = true; 144 | if ($upload) { 145 | try { 146 | $root = $is_snap ? 'snaps' : 'releases'; 147 | $frag = $ext->getVendor() . "/" . $ext->getName(); 148 | $target = '/' . $root . '/' . $frag . '/' . $ext->getVersion(); 149 | 150 | $pkgs_to_upload = $build_error ? array() : array($pkg_file); 151 | 152 | if ($build_error) { 153 | echo "Uploading logs" . PHP_EOL; 154 | } else { 155 | echo "Uploading '$pkg_file' and logs" . PHP_EOL; 156 | } 157 | 158 | if ($build_error && !file_exists($logs_zip)) { 159 | throw new Exception("Logs wasn't packaged, nothing to upload"); 160 | } 161 | 162 | if (rm\upload_pickle_pkg_ftp_curl($pkgs_to_upload, array($logs_zip), $target)) { 163 | echo "Upload succeeded" . PHP_EOL; 164 | if (file_exists($logs_zip)) { 165 | unlink($logs_zip); 166 | } 167 | if (file_exists($pkg_file)) { 168 | unlink($pkg_file); 169 | } 170 | } else { 171 | throw new Exception("Upload failed"); 172 | } 173 | } catch (Exception $e) { 174 | echo 'Error . ' . $e->getMessage() . PHP_EOL; 175 | $upload_success = false; 176 | } 177 | } 178 | /* keep recording upload status for every package, the code at the end is going to evaluate it like in pecl. */ 179 | $upload_status[$build_name] = $upload_success; 180 | 181 | /* notify pickle */ 182 | 183 | echo PHP_EOL; 184 | } 185 | 186 | if ($is_last_run) { 187 | if (file_exists($job_path)) { 188 | unlink($job_path); 189 | } 190 | 191 | if (file_exists($pkg_path)) { 192 | unlink($pkg_path); 193 | } 194 | } 195 | 196 | exit(0); 197 | 198 | -------------------------------------------------------------------------------- /script/pickle_ctl.php: -------------------------------------------------------------------------------- 1 | cleanup(); 43 | 44 | $pw = new rm\PickleWeb($sync_host, new rm\PickleDb($db_dir)); 45 | 46 | if (!$pw->updatesAvailable()) { 47 | echo "No updates available"; 48 | exit(0); 49 | } 50 | 51 | $news = (array)$pw->getNewTags(); 52 | 53 | foreach ($news as $job) { 54 | $aa->add($job); 55 | } 56 | } catch (Exception $e) { 57 | echo $e->getMessage() . "\n"; 58 | exit(3); 59 | } 60 | 61 | } 62 | 63 | 64 | 65 | exit(0); 66 | 67 | -------------------------------------------------------------------------------- /script/snap.php: -------------------------------------------------------------------------------- 1 | 4) { 9 | echo "Usage: snapshot [force 1/0]\n"; 10 | exit(); 11 | } 12 | 13 | $have_build_run = false; 14 | $branch_name = $argv[1]; 15 | $build_type = $argv[2]; 16 | $force = isset($argv[3]) && $argv[3] ? true : false; 17 | $sdk_arch = getenv("PHP_SDK_ARCH"); 18 | if (!$sdk_arch) { 19 | throw new \Exception("Arch is empty, the SDK might not have been setup. "); 20 | } 21 | $all_branch_confs_path = __DIR__ . '/../data/config/branch'; 22 | $config_path = $all_branch_confs_path . '/' . $sdk_arch . '/' . $branch_name . '.ini'; 23 | $req_builds_num = rm\BranchConfig::getRequiredBuildsNum($all_branch_confs_path, $branch_name); 24 | 25 | $err_msg = NULL; 26 | try { 27 | $branch = new rm\Branch($config_path, $req_builds_num); 28 | } catch (\Exception $e) { 29 | $err_msg = $e->getMessage(); 30 | goto out_here; 31 | } 32 | 33 | if (!$branch->requiredBuildRunsReached() && $branch->numBuildsRunning() == $req_builds_num) { 34 | $err_msg = "Waiting for " . $branch->getLastRevisionId() . " builds to finish."; 35 | goto out_here; 36 | } 37 | 38 | $branch_name = $branch->config->getName(); 39 | $branch_name_short = $branch->config->getBranch(); 40 | 41 | echo "Running <" . realpath($config_path) . ">\n"; 42 | echo "\t$branch_name\n"; 43 | 44 | //var_dump($branch->hasNewRevision(), !$branch->isLastRevisionExported($branch->getLastCommitId()) && $branch->hasUnfinishedBuild()); 45 | 46 | if ($branch->hasNewRevision() || !$branch->isLastRevisionExported($branch->getLastCommitId()) && $branch->hasUnfinishedBuild()|| $force) { 47 | 48 | try { 49 | if (!$branch->update("all" == $build_type ? NULL : $build_type)) { 50 | goto out_here; 51 | } 52 | } catch (\Exception $e) { 53 | $err_msg = $e->getMessage(); 54 | goto out_here; 55 | } 56 | 57 | $last_rev = $branch->getLastRevisionId(); 58 | $prev_rev = $branch->getPreviousRevision(); 59 | 60 | echo "\tprevious revision was: $prev_rev\n"; 61 | echo "\tlast revision is: $last_rev\n"; 62 | 63 | $have_build_run = true; 64 | echo "processing revision $last_rev\n"; 65 | 66 | $build_dir_parent = $branch->config->getBuildLocation(); 67 | 68 | if (!is_dir($build_dir_parent)) { 69 | if(!mkdir($build_dir_parent, 0777, true)) { 70 | echo "Couldn't create build location"; 71 | exit(-1); 72 | } 73 | } 74 | 75 | if (strlen($last_rev) == 40) { 76 | $last_rev = substr($last_rev, 0, 7); 77 | } 78 | $src_original_path = $branch->createSourceSnap($build_type, $last_rev); 79 | 80 | $toupload_dir = TMP_DIR . '/' . $branch_name . '/r' . $last_rev . '-builds/'; 81 | if (!is_dir($toupload_dir)) { 82 | mkdir($toupload_dir, 0655, true); 83 | } 84 | 85 | if (!is_dir($toupload_dir . '/logs')) { 86 | mkdir($toupload_dir . '/logs', 0655, true); 87 | } 88 | 89 | copy($src_original_path . '.zip', $toupload_dir . '/' . $branch_name . '-src-r'. $last_rev . '.zip'); 90 | $builds = $branch->getBuildList('windows'); 91 | 92 | $has_build_errors = false; 93 | $build_errors = array(); 94 | 95 | foreach ($builds as $build_name) { 96 | if ($build_type != 'all') { 97 | if ($build_name != $build_type) { // i.e. nts-windows-vc9-x86 98 | continue; 99 | } 100 | else { 101 | echo "Starting build for $build_name\n"; 102 | } 103 | } 104 | 105 | $build_src_path = realpath($build_dir_parent) . DIRECTORY_SEPARATOR . $build_name; 106 | $log = rm\exec_single_log('mklink /J ' . $build_src_path . ' ' . $src_original_path); 107 | if (!file_exists($build_src_path)) { 108 | throw new \Exception("Couldn't link '$src_original_path' to '$build_src_path'"); 109 | } 110 | 111 | $build = $branch->createBuildInstance($build_name); 112 | try { 113 | $build->setSourceDir($build_src_path); 114 | 115 | echo "Updating dependencies\n"; 116 | /* XXX Pass stability from script arg. */ 117 | $ret = $build->updateDeps("staging"); 118 | echo $ret["log"] . "\n"; 119 | 120 | echo "running build in <$build_src_path>\n"; 121 | $build->buildconf(); 122 | if ($branch->config->getPGO() == 1) { 123 | $need_pgo_build = true; 124 | /* For now it is enough to just get a very same 125 | build of PHP to setup the environment. This 126 | only needs to be done once for setup. In further 127 | also, if there are any difference with TS/NTS, 128 | there might be some separate setup needed. */ 129 | $build->pgoInitLock(); 130 | if (!$build->isPgoSetup()) { 131 | echo "Preparing PGO training environment\n"; 132 | $build->configure(); 133 | $build->make(); 134 | $build->pgoInit(); 135 | } 136 | $build->pgoInitUnlock(); 137 | echo "Creating PGI build\n"; 138 | $build->configure(' "--enable-pgi" '); 139 | } 140 | else { 141 | $need_pgo_build = false; 142 | $build->configure(); 143 | } 144 | $build->make(); 145 | /* $html_make_log = $build->getMakeLogParsed(); */ 146 | if ($branch->config->getPGO() == 1) { 147 | echo "Creating PGO build\n"; 148 | try { 149 | // if training fails, we still can go on for snaps 150 | $build->pgoTrain(); 151 | } catch (Exception $e) { 152 | echo $e->getMessage() . "\n"; 153 | echo $build->log_buildconf; 154 | } 155 | $build->make(' clean-pgo'); 156 | $build->configure(' "--with-pgo" ', false); 157 | $build->make(); 158 | $html_make_log = $build->getMakeLogParsed(); 159 | $need_pgo_build = false; 160 | } 161 | $build->makeArchive(); 162 | } catch (Exception $e) { 163 | echo $e->getMessage() . "\n"; 164 | echo $build->log_buildconf; 165 | } 166 | 167 | if ($build->archive_path) { 168 | copy($build->archive_path, $toupload_dir . '/php-' . $branch_name_short . '-' . $build_name . '-r'. $last_rev . '.zip'); 169 | } 170 | if ($build->archive_path) { 171 | copy($build->devel_path, $toupload_dir . '/php-devel-pack-' . $branch_name_short . '-' . $build_name . '-r'. $last_rev . '.zip'); 172 | } 173 | if ($build->archive_path) { 174 | copy($build->debug_path, $toupload_dir . '/php-debug-pack-' . $branch_name_short . '-' . $build_name . '-r'. $last_rev . '.zip'); 175 | } 176 | if ($build->test_path) { 177 | $tmp = str_replace(array('-ts', '-nts'), array('',''), $build_name); 178 | copy($build->test_path, $toupload_dir . '/php-test-pack-' . $branch_name_short . '-' . $tmp . '-r'. $last_rev . '.zip'); 179 | } 180 | 181 | file_put_contents($toupload_dir . '/logs/buildconf-' . $build_name . '-r'. $last_rev . '.txt', $build->log_buildconf); 182 | file_put_contents($toupload_dir . '/logs/configure-' . $build_name . '-r'. $last_rev . '.txt', $build->log_configure); 183 | file_put_contents($toupload_dir . '/logs/make-' . $build_name . '-r'. $last_rev . '.txt', $build->log_make); 184 | file_put_contents($toupload_dir . '/logs/archive-' . $build_name . '-r'. $last_rev . '.txt', $build->log_archive); 185 | if ($branch->config->getPGO() == 1) { 186 | file_put_contents($toupload_dir . '/logs/pgo-' . $build_name . '-r'. $last_rev . '.txt', $build->log_pgo); 187 | } 188 | 189 | $html_make_log = $build->getMakeLogParsed(); 190 | file_put_contents($toupload_dir . '/logs/make-' . $build_name . '-r'. $last_rev . '.html', $html_make_log); 191 | copy(__DIR__ . '/../template/log_style.css', $toupload_dir . '/logs/log_style.css'); 192 | 193 | if ($need_pgo_build) { 194 | $stats = ['warning' => 0, 'error' => 1]; 195 | } else { 196 | $stats = $build->getStats(); 197 | } 198 | 199 | $json_filename = $build_name . '.json'; 200 | 201 | $json_data = array( 202 | 'stats' => $stats, 203 | 'has_php_pkg' => file_exists($build->archive_path), 204 | 'has_debug_pkg' => file_exists($build->debug_path), 205 | 'has_devel_pkg' => file_exists($build->devel_path), 206 | 'has_test_pkg' => file_exists($build->test_path), 207 | ); 208 | 209 | if ($stats['error'] > 0) { 210 | $has_build_errors = true; 211 | if ($need_pgo_build) { 212 | $json_data['build_error'] = ['PGO build not attempted']; 213 | } else { 214 | $build_errors[$build_name] = $build->compiler_log_parser->getErrors(); 215 | $json_data['build_error'] = $build_errors[$build_name]; 216 | } 217 | } 218 | 219 | $json = json_encode($json_data); 220 | file_put_contents($toupload_dir . '/' . $json_filename, $json); 221 | 222 | // $build->clean(); 223 | rmdir($build_src_path); 224 | 225 | $branch->buildFinished(); 226 | } 227 | 228 | $src_dir = $branch_name . '/r' . $last_rev; 229 | rm\upload_build_result_ftp_curl($toupload_dir, $src_dir); 230 | /* FIXME This is still not safe, locking needed! */ 231 | foreach (["$toupload_dir/logs", $toupload_dir] as $path) { 232 | $items = scandir($path); 233 | foreach ($items as $item) { 234 | $full = $path . "/" . $item; 235 | if (is_file($full)) { 236 | @unlink($full); 237 | } 238 | } 239 | } 240 | //rm\rmdir_rf($toupload_dir); 241 | 242 | $branch->setLastRevisionExported($last_rev); 243 | } 244 | 245 | out_here: 246 | if ($err_msg) { 247 | echo "$err_msg\n"; 248 | } else if (!$have_build_run) { 249 | echo "no new revision.\n"; 250 | } 251 | 252 | if ($have_build_run) { 253 | /*Upload the branch DB */ 254 | $try = 0; 255 | do { 256 | $status = rm\upload_file_curl($branch->db_path, $branch_name . '/' . basename($branch->db_path)); 257 | $try++; 258 | } while ( $status === false && $try < 10 ); 259 | $branch->resetBuildInfo(); 260 | } 261 | 262 | //if ($has_build_errors) { 263 | // rm\send_error_notification($branch_name, $build_errors, $branch->getPreviousRevision(), $last_rev, 'http://windows.php.net/downloads/snaps/' . $branch_name . '/r' . $last_rev); 264 | //} else { 265 | /* if no error, let update the snapshot page */ 266 | // rm\update_snapshot_page(); 267 | //} 268 | 269 | echo "Done.\n"; 270 | -------------------------------------------------------------------------------- /template/log_style.css: -------------------------------------------------------------------------------- 1 | body {background-color: #ffffff;font-size: 80.01%; /* 12px [1] */color: black;font-family: arial, sans-serif;padding: 1em;margin: 0em;} 2 | #log {margin-top:.5em;} 3 | #log .con{font-size:small;color:#000;} 4 | #log .l { color:#666; } 5 | #log .m {background-color:#ffb;} 6 | #log i {color: green; font-weight:bold;} 7 | #log tr.dir{background-color:#C5D5A9;} 8 | #log td.f{width:3em;padding-left:2em;padding-right:.5em;} 9 | #log .alt {background-color: #E8E8F0;} 10 | #log td.error{background-color: #FF0000;} 11 | #log td.warning{background-color: #FF9966;} 12 | #log td.lib{background-color: #FF9933;} 13 | -------------------------------------------------------------------------------- /template/mail_notification.tpl.php: -------------------------------------------------------------------------------- 1 | This is an automatic mail from the rmtoool's build bots. 2 | 3 | New build errors have been introduced between 4 | and . 5 | 6 | The errors are: 7 | 8 | 9 | 10 | Full logs are available at (htmlized versions too): 11 | 12 | 13 | -------------------------------------------------------------------------------- /template/make_log.tpl.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | <?php echo $title; ?> 9 | 10 | 11 |

12 |
13 | 14 | 15 | 18 | 19 | 51 | >> 52 | 53 |
File:LineLevelCodeMessage
 
54 |
55 | 56 | 57 | -------------------------------------------------------------------------------- /tmp/.dummy: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/web-rmtools/68e1116d4740c32d21791e122683a8589748e3e4/tmp/.dummy --------------------------------------------------------------------------------