Compare commits

..

128 Commits

Author SHA1 Message Date
Anatol Belski
c3cf4266ad Prepare 2.1.3 release 2018-03-29 16:50:36 +02:00
Anatol Belski
01e4fff84a Upgrade vswhere 2018-03-28 18:11:39 +02:00
Anatol Belski
4357adc956 Back to dev 2018-03-21 13:12:34 +01:00
Anatol Belski
0a33374aed Prepare 2.1.3beta1 2018-03-21 13:09:49 +01:00
Anatol Belski
ff16eebfce Update CA certs 2018-03-19 14:49:18 +01:00
Anatol Belski
afc302d27e Upgrade MSYS2 tools at once 2018-03-19 14:46:33 +01:00
Anatol Belski
e6c79ecad5 Update README 2018-03-19 13:03:44 +01:00
Anatol Belski
80dc35f668 Upgrade re2c 2018-03-19 13:03:22 +01:00
Anatol Belski
bd3e1603a9 Upgrade bundled PHP 2018-03-19 12:51:23 +01:00
Anatol Belski
8505dda9c4 Back to dev 2018-03-14 11:53:39 +01:00
Anatol Belski
b15cdb1f92 Prepare 2.1.2 2018-03-14 11:53:04 +01:00
Anatol Belski
91302e8142 Use SSL explicitly for communitation with windows.php.net 2018-03-12 14:03:00 +01:00
Anatol Belski
f655bcf7d1 Upgrade vswhere 2018-03-12 11:22:11 +01:00
Alexander Gabriel
89bc6e0eb8 Using PHP-X.Y would not work. 2018-03-05 11:29:18 +01:00
Anatol Belski
4d9b189d04 Increase version for dev 2018-02-20 15:33:05 +01:00
Anatol Belski
ff33ae5143 Prepare 2.1.1 2018-02-20 15:32:09 +01:00
Anatol Belski
3cf0f67f27 More robust network error handling 2018-02-20 14:37:15 +01:00
Anatol Belski
b0a93f01c5 Send user agent when fetching 2018-02-20 10:34:30 +01:00
Anatol Belski
e10c86c2d5 Avoid fetching series more than once in the same run 2018-02-20 09:31:08 +01:00
Anatol Belski
20ccc545bd Further notes on custom training case implementation 2018-02-02 17:03:02 +01:00
Anatol Belski
0be0ba3a84 Back to dev 2018-02-02 13:55:54 +01:00
Anatol Belski
c2e3b0ec40 Prepare 2.1.0 2018-02-02 13:54:32 +01:00
Anatol Belski
b0b61457b4 Add note on training case contributing 2018-02-02 13:18:06 +01:00
Anatol Belski
c4ba07a627 Make it a link 2018-02-02 13:15:12 +01:00
Anatol Belski
2c54b0baf5 Edits to PGO description 2018-02-02 13:13:39 +01:00
Anatol Belski
ca942978ee Upgrade 7za 2018-02-02 12:53:12 +01:00
Anatol Belski
6153bb9af2 Mention phpsdk_pgo 2018-02-02 12:44:38 +01:00
Anatol Belski
c4ce390679 Change wording 2018-02-02 09:57:11 +01:00
Anatol Belski
2040ea78bd Use new URLs 2018-02-02 09:42:46 +01:00
Anatol Belski
90f5c1633e Make it a link 2018-02-02 09:41:53 +01:00
Anatol Belski
5a44f0b05d Extend PGO doc 2018-02-02 09:40:14 +01:00
Anatol Belski
c84b3e6b9e Inc minor
The addition of the PGO features is what makes impact.
2018-02-02 08:41:50 +01:00
Anatol Belski
a861392d45 Fix typos 2018-02-02 08:40:11 +01:00
Anatol Belski
0474318721 Remove irrelevant part 2018-02-02 08:31:10 +01:00
Anatol Belski
b21fad7268 Update doc 2018-02-02 08:28:44 +01:00
Anatol Belski
5748dedb3b Update year and fix eol 2018-02-01 17:33:37 +01:00
Anatol Belski
4cea7a4f66 Upgrade bundled PHP 2018-02-01 17:25:23 +01:00
Anatol Belski
7e8235f1a1 Upgrade vswhere 2018-02-01 17:18:20 +01:00
Anatol Belski
1122cbd9d9 Merged PGO integration branch
Squashed commit of the following:

commit 0b963bf9926cfb23b82de5c5ecb802c23ee1d91b
Merge: b0b5b9c 1684c7e
Author: Anatol Belski <ab@php.net>
Date:   Fri Nov 17 15:11:22 2017 +0100

    Merge branch 'master' into pgo_integration

    * master:
      Back to dev
      Prepare 2.0.13
      Upgrade vswhere
      Upgrade bundled PHP
      Unset some tmp vars
      Note on unattended build
      Check for Windows SDK 10.0 for VC14, too
      Pass nologo to vcvarsall.bat
      Unify EOL
      Ensure starter scripts keep the current directory
      Update version in readme
      Add comment
      Fix curl error handling

commit b0b5b9c6e7c2695968b8c184ba4f1542d83261ec
Author: Anatol Belski <ab@php.net>
Date:   Mon Oct 30 14:58:33 2017 +0100

    Warn if a job file is not present, maybe SDK needs reinit

commit d84a2e8432d424471d5aeb77911f71b2d2bb377c
Author: Anatol Belski <ab@php.net>
Date:   Mon Oct 30 07:39:33 2017 +0100

    Add --scenario to the help

commit 9556fad5e5869a6d9ac150ace863c5c304d7c100
Author: Anatol Belski <ab@php.net>
Date:   Sat Oct 28 18:22:31 2017 +0200

    Add scenario based on https://github.com/01org/php_pgo_training_scripts

commit c4e32bbc7142680796a726980a089d98d310797a
Merge: 11dcbc8 1ba1bf1
Author: Anatol Belski <ab@php.net>
Date:   Thu Oct 26 19:32:24 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Back to dev
      Prepare 2.0.12
      Reflect re2c version
      Note about fetching
      Add note about UNIX flavors
      Reflect bison version
      Rephrase
      Back to dev
      Prepare beta3
      Rebase MSYS2 DLLs
      Turn back to dev
      Prepare 2.0.12beta2
      Add missing DLLs
      Back to dev
      Prepare 2.0.12beta1
      Upgrade vswhere
      Upgrade msys2 tools
      Back to dev
      2.0.11

commit 11dcbc88b754729c97aef70442bb1223a142ce09
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 15 11:23:34 2017 +0200

    Add locking to the PGO training and init actions

commit aca33a7e3813e894fa2a0457e31efabaf3e9d3fb
Merge: bcb8fcf c7c874e
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 15 10:48:06 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Improve messaging for locked dependency path

commit bcb8fcf366353b69c6091d30bf3f9859b890ea66
Merge: d86027f 97112e4
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 15 10:36:50 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Refactor lock also wrt shared/exclusive
      Folds

commit d86027fdcca2916c5a31cf24afa540ce90a18249
Merge: 253d590 a5afa11
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 15 09:22:41 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Integrate locking into the dep update process
      Fix and improve lock class
      Add locker class
      Lock while caching
      Folds

commit 253d5908fb57a4e79f08ecbc36a924f0abb42481
Merge: ea6d9d9 d802183
Author: Anatol Belski <ab@php.net>
Date:   Tue Sep 5 18:28:01 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Adjust description
      Support branch recognition when working under dev package

commit ea6d9d957407d98dd05651d87aa3bb173030e679
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 1 16:47:06 2017 +0200

    Increase runs number

commit 157af24f4b3bfc3fee123bdb1ae466cd5295260e
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 1 14:19:07 2017 +0200

    Prepare some debug piece

commit 74ce6dd35020fb7de6277335a17ac7487fddd23b
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 1 14:10:03 2017 +0200

    More for error logging

commit d17b00261ee7d1b70e202010d7946f411b10db7b
Merge: 30dc3ff a97d0bd
Author: Anatol Belski <ab@php.net>
Date:   Fri Sep 1 15:57:21 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Fix Arch determintion
      Add pretty option
      Rework dllmap script
      Note pwgen presence

commit 30dc3ff3c2944dfca7b6d7446ca0cf365c12746e
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 14:18:41 2017 +0200

    Fix binary path

commit e1f2d9c4aaa61ba176cdc22ecd667d617ce315a4
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 14:10:01 2017 +0200

    Extend the firewall template

commit 7cab2769a146fdbd85e4118589962f984d3ca521
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 13:40:57 2017 +0200

    Fix syntax error

commit 74760b1d339ed66ff02f09b1a3ccd11fb9823a8a
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 13:39:31 2017 +0200

    Fix syntax error

commit 9ee0f9f564edcf82893cc8cbe57942b816f54edc
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 13:37:50 2017 +0200

    Typehints

commit 6a86ff3399425224affd35ef97e58f416f9724cb
Merge: a71e63d de669c7
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 13:08:55 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Back to dev
      2.0.10

commit a71e63d44046d503af4a9cbc759ff41f2bc27246
Merge: 5021a30 ceececf
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 13:06:12 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Improve the pack command, show more info and translate the exit code

commit 5021a30fa1a1d9f2f28925504aa4f5b6cacedfae
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 28 12:42:15 2017 +0200

    Add possibility to mark cases inactive

    and turn off the mediawiki case for now.

commit 04f267114f3f5a9d2e53dc7b37dc16e948f71199
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 25 11:23:17 2017 +0200

    Rework HTTP code evaluation and URL setup

commit c6c405968e99c1ceb169eed45f07cef3259aa376
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 15:08:00 2017 +0200

    Further INI templating per scenario

commit 9be8f65856c5ff6d7f313d7b4693f5730e20dc9a
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 13:34:41 2017 +0200

    Decrease numbers yet more, otherwise it's an issue on 32-bit

    Still need to workout something for 64/32-bit separation

commit 6dfe66dcafc8c3c68448a1b1c1fe46d5a5d5ab8e
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 13:31:08 2017 +0200

    Fix wrong ini, no Opcache cli

commit c0556fac6bcb0c609367f93fae302f149d1cde48
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 13:25:26 2017 +0200

    Revert numbers and increase timeout

commit dbc86f72c8de1a7851632285e5eb1efcee1189ca
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 12:50:20 2017 +0200

    Show the training scenario being used

commit c67a5eea36bb97dc2bcae5097abc143c15676e81
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 12:45:23 2017 +0200

    Don't enable opcache on CLI and adjust some numbers

commit 0ec768ca40d11bd84b53b040a42aaf994d9a9f23
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 10:42:55 2017 +0200

    Set fastcgi_read_timeout

commit 6145b841b5f086b7c7f9a02f0d9fd1d41fae4cf2
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 24 10:30:43 2017 +0200

    Set select timeout

commit 600ea8518f5ca2bbbbcc65c8772d283da0da2a15
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 23 22:56:28 2017 +0200

    Keep FCGI childer some longer alive

commit f6a95c50c5bcb2673721bb63146f87a8fbdcf2c5
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 23 22:51:47 2017 +0200

    Exclude most of the extension not directly trained

commit 87f4d7393167944108b40b34a6eee1c250f4587d
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 23 18:36:54 2017 +0200

    Adjust error_log filename

commit e22caaeb390433d3cf6d6dc3322d6ab385780436
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 23 16:48:47 2017 +0200

    Write error log into the build dir

commit 7bd80a6952bbcef1bbd6e446964285731d898b8e
Merge: acadf54 64c2ac9
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 23 00:20:01 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Fix deps path recognition
      add deps package command
      reset errorlevel before tool run, set the current on exit

commit acadf54f1576aa81c25613a0121898675777edf7
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 22:40:12 2017 +0200

    Rework the server up routines a bit

commit 6948d0fb99f8f9d52c26d8a6f20aa8de5869b878
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 17:48:48 2017 +0200

    Increase/add startup timeouts

commit d494d3cec28072eb0bf50c5a778a36ec4e86e7ce
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 14:09:59 2017 +0200

    Add redirect URL to the stats

commit 1172928f360b6363bc559c176a3557a821c0e478
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 13:54:33 2017 +0200

    Fix warning

commit ec37bbca6d5ca5a42b4287cceb1decbe414a103a
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 13:48:15 2017 +0200

    Improve Mediawiki URL generation

commit 66280db114863ef221fb33a04734e227adadbb0b
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 13:41:51 2017 +0200

    Add more info about non 200 codes

commit 2fcab615715922ff83076e82ba24a7389a1f1d09
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 11:33:36 2017 +0200

    Set error_log = syslog

commit 0ac29c3d5dd3f5e929970f59c647100c4432ebab
Author: Anatol Belski <ab@php.net>
Date:   Tue Aug 22 11:09:44 2017 +0200

    Back to 8 max children

commit 67cced2a4220b8af809e8ebe7d508c84b7c85735
Author: Anatol Belski <ab@php.net>
Date:   Sat Aug 19 11:07:46 2017 +0200

    set explicit timeouts

commit 491abac200aae57f379be0393f7ed7b061af8089
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 23:43:22 2017 +0200

    Use generated config, if available

commit 2ae06304248b0b149a5a3201d619e7edcd330455
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 23:07:01 2017 +0200

    Revert "extend is initialized check"

    This reverts commit f365e530cff348bb656a9dd8c887143e9e0559a5.

commit f365e530cff348bb656a9dd8c887143e9e0559a5
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 12:36:16 2017 +0200

    extend is initialized check

commit 7905dccad49fc55c26e5d07a8f731c2e21bbbf26
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 10:50:25 2017 +0200

    lower default number of fcgi processes

commit 5df59c3a3f0f8c46520bf498e52bfe76506d54d9
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 02:59:08 2017 +0200

    some new keys can also be added to the env

commit 5ee2edca7a94a60505924ae998cc647fd332916a
Author: Anatol Belski <ab@php.net>
Date:   Fri Aug 18 00:15:27 2017 +0200

    fix image name

commit b3cadbd2061f0e9c10516fed07e03d6999bd9117
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 23:35:51 2017 +0200

    deactivate joomla training case for now

commit 23baf7931c3d08b6e95d8425cb197365429a0e7e
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 22:21:58 2017 +0200

    fix mysql availability for the external tools

commit 77f6519255bb6ab57bf9c5014ba7a3b8ea394eb2
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 20:25:12 2017 +0200

    fix path separator

commit 63bc4d515256f2bcd68a32b87b5dd095575e49b2
Merge: e4a51d6 eae3aab
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 18:19:40 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      revert the deps path reset part and sync

commit e4a51d67c417829ae78ae5c90fa3b7f9936bdb96
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 16:35:32 2017 +0200

    should be fixed by the previous commit

commit 77e0b65e218710baf456633f880564a8ab50fd37
Merge: 104f57c e7e92b3
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 16:34:33 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      yet more path recognition variant

commit 104f57c232e5f2689a6e7d10415fcb5e95d96003
Merge: aa62653 d158c3c
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 16:19:31 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      add possibility to reevaluate the deps path

commit aa62653187c356897cdd9f0967b8c6553e5e0ba9
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 16:19:08 2017 +0200

    reevaluate deps path

commit 5b54583f7a512a5d774907d9693950b6c82a5241
Merge: 295d9ca 69fb69f
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 15:34:07 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      no realpath needed

commit 295d9cad733884a9588a1949078f5fd4f61e98a6
Merge: c2e9b1d aee165f
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 14:06:43 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      refactor dependency dir recognition

commit c2e9b1d1645e6ff7f54ec308b82292ced9080e56
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 11:19:12 2017 +0200

    rephrase

commit d7f8be2b954fa3eddca8ba0ad7947230c2cdf45a
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 11:14:50 2017 +0200

    some PGO doc

commit 16434a8aff4fcff85d68ecb431691f6d50be5f6e
Author: Anatol Belski <ab@php.net>
Date:   Thu Aug 17 10:37:45 2017 +0200

    add template script for opening required ports

commit 4aa9cba50a9f44fa021f1680ddbfe8073aa4cfcc
Merge: d7f5e8c 0223331
Author: Anatol Belski <ab@php.net>
Date:   Sat Aug 12 14:36:23 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      upgrade vswhere
      extend .gitignore

commit d7f5e8cc6cd331814fe5650bb5a7a97e41453e73
Author: Anatol Belski <ab@php.net>
Date:   Wed Aug 9 22:58:34 2017 +0200

    add ready mode for pgo

commit 8b64fb7f5e43b488c8628440df28698443908e9b
Author: Anatol Belski <ab@php.net>
Date:   Mon Aug 7 18:30:19 2017 +0200

    add 7.3 inis

commit 323188a802abcb1a32fb5a14a64ba52fa51cfd19
Merge: e18835e 7d72596
Author: Anatol Belski <ab@php.net>
Date:   Wed Jul 26 17:04:27 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      back to dev
      prepare 2.0.9
      sync with eol change

commit e18835e055ecc41818d1b1bfac7ba7705153a515
Author: Anatol Belski <ab@php.net>
Date:   Sun Jul 23 21:00:44 2017 +0200

    EOL changes

commit 678173e046b0beac56182a31e16354c0533b0a50
Merge: dd2527b eaa6ff5
Author: Anatol Belski <ab@php.net>
Date:   Sun Jul 23 20:58:32 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      add more file types for eol mitigation
      extend redme

commit dd2527b248798bcbff1b0f675b40015069c07d4f
Merge: 0922158 0319dc0
Author: Anatol Belski <ab@php.net>
Date:   Sun Jul 23 20:43:00 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      add gitattributes
      add comment

commit 092215893e3480ec693fba67702b9b65d494402c
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 20:52:24 2017 +0200

    improve url extraction

commit f650e1e7ebef4d43fa0e9e9cc9054baa090be90b
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 20:35:45 2017 +0200

    add basic mediawiki support

commit 538fe384e708a3f5194eed153a933e73cd4278e8
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 20:34:49 2017 +0200

    comment out PostgreSQL for now

commit 84e7a027d366ada3aafe3d9cf988660d0060c73a
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 20:31:43 2017 +0200

    comment out debug piece

commit e096090f17f14a681a32285ad5ffdda45ca91cc8
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 18:19:25 2017 +0200

    some reworks, mainly to improve postgres handling

commit 263786e8300fa1a4f8b3ee1ab3a21d8bd8802dac
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 11:12:28 2017 +0200

    enable pgsql ext for training

commit 4471fc5dfce5a9c75b818540c8a0772a4445c4f7
Author: Anatol Belski <ab@php.net>
Date:   Fri Jul 21 09:42:18 2017 +0200

    remove debug output

commit fd1467850919d003d4e66beb18d4005ceb212774
Merge: ccb26ee 55fddef
Author: Anatol Belski <ab@php.net>
Date:   Thu Jul 20 23:55:26 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      back to dev
      prepare 2.0.8

commit ccb26eebeed1c637c4ce603bc68ff45aaebc680e
Author: Anatol Belski <ab@php.net>
Date:   Thu Jul 20 18:15:11 2017 +0200

    add Joomla support

commit 9e71002f9017c2ebc9509b75c3798207e18e8e87
Author: Anatol Belski <ab@php.net>
Date:   Thu Jul 20 15:56:23 2017 +0200

    add basic composer fetch

commit 21956c5dca4a7c0f99cc15cf3457b5d9722d3c6f
Merge: 63f3263 8e3d439
Author: Anatol Belski <ab@php.net>
Date:   Tue Jul 18 20:35:31 2017 +0200

    Merge branch 'master' into pgo_integration

    * master:
      Support also preview releases
      upgrade bundled php
      back to dev
      prepare 2.0.7
      improve branch name guessing
      fixed option handling, thanks Kalle
      upgrade to vswhere 2.0.2
      extend deps update comment
      task.exe commen

commit 63f3263b2b129d1de4e83533f9b6d2b8eb1712e4
Merge: a0d8788 9e5e7e6
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 16 02:43:11 2017 +0200

    Merge branch 'master' into pgo_integration

commit a0d8788233633231ac1f7a5208284edacbb7ec6b
Author: Anatol Belski <ab@php.net>
Date:   Wed Jun 7 17:48:25 2017 +0200

    change default pg port, add some util methods

commit 661fe8992638c4af92793f8464038ac5dc044f5b
Author: Anatol Belski <ab@php.net>
Date:   Wed Jun 7 14:24:14 2017 +0200

    basic Postgres stuff

commit 7b3b0b96184cfe89c052292ef6e71aa05f96b548
Author: Anatol Belski <ab@php.net>
Date:   Wed Jun 7 14:23:34 2017 +0200

    remove dead code

commit 00670fdc005244c26ff9248857de264e344d9348
Author: Anatol Belski <ab@php.net>
Date:   Wed Jun 7 13:23:34 2017 +0200

    respect mariadb port, user creation is still to go if needed

commit b73f3eda83152e526bd6eaba8a3c3470a696b300
Author: Anatol Belski <ab@php.net>
Date:   Wed Jun 7 13:22:28 2017 +0200

    fix wrong merge

commit 6ca5d948e173956618bd541a2daf26e92bfe7748
Merge: 7d8bd88 99efb73
Author: Anatol Belski <ab@php.net>
Date:   Mon Jun 5 21:01:47 2017 +0200

    Merge branch 'master' into pgo_integration

commit 7d8bd88b029b3c05e072f77d2c287bee51f58672
Author: Anatol Belski <ab@php.net>
Date:   Mon Jun 5 13:39:33 2017 +0200

    forcibly propagate errorlevel

commit d2f3bb5245640e3f5a1b44530be3ed2df775ee53
Author: Anatol Belski <ab@php.net>
Date:   Mon Jun 5 13:38:16 2017 +0200

    forcibly propagate errorlevel

commit 0d5c0dc71ce4dd4b4578d490cccd28ebcd830de3
Author: Anatol Belski <ab@php.net>
Date:   Sat Jun 3 10:21:41 2017 +0200

    hide warning

commit 276c3cdd6214d974e294bf177f601ebf8d33f92d
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 2 21:46:56 2017 +0200

    remove existing dir before renaming

commit 2bc6e2324de50d43c74e48e30a6a0799f892aa22
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 2 21:35:32 2017 +0200

    fix reinit and clean init mode

commit 8527d983cf43b32d5efbf3674cebfb62302e4e7a
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 2 21:11:48 2017 +0200

    lower wp-cli version, seems there are issues with 1.2.0

commit fbad30b92e9d498e2fadee4ac38f99c0ab825a17
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 2 21:07:30 2017 +0200

    more compact code using a worker for init preparation

commit 83c24e93f6ceaa2d55f070e92713a8b91362e27f
Author: Anatol Belski <ab@php.net>
Date:   Fri Jun 2 17:19:59 2017 +0200

    allow rename dest dir when unzip

commit 81f0d6f24db4af54a161e1cd1b258618cea47809
Author: Anatol Belski <ab@php.net>
Date:   Thu Jun 1 21:44:02 2017 +0200

    don't keep merged pgc files

commit 8b9fd7ee7c2437645755b69560630399e15ac31e
Author: Anatol Belski <ab@php.net>
Date:   Thu Jun 1 21:21:23 2017 +0200

    fix wptest dir name

commit e29b5bb7d89f7da5f71eabfa2c3f06e7a514a059
Author: Anatol Belski <ab@php.net>
Date:   Thu Jun 1 21:20:36 2017 +0200

    ups

commit d18fba6792e23f17fac605d1ea432fc3048e862d
Author: Anatol Belski <ab@php.net>
Date:   Thu Jun 1 20:56:27 2017 +0200

    full implement wordpress init/train

commit 2a5000c399f799ed3c56bbd61305c4fd7a395c09
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 19:43:45 2017 +0200

    more fine clean

commit 7b736c135fa3c1131d0a2f53b2de477f77904f12
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 19:12:06 2017 +0200

    cleanup the pgc files before training starts

commit 63ea1c84425ba56df8fd0f789a884bfe6c859018
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 18:03:48 2017 +0200

    Implement training with PGO data dumping

commit 57b529646182344f7962a966347957da97d6c934
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 16:12:02 2017 +0200

    fix nginx init

commit 76aee824bb21f2298bb484aa6d60d5448cb4c985
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 15:55:55 2017 +0200

    next round refactor already done stuff

commit c8ce3afec0225028375c81fcc40a13ba7e0cd23a
Author: Anatol Belski <ab@php.net>
Date:   Wed May 31 00:05:15 2017 +0200

    start to implement training, improve templating

commit 61837905abb18bef86ad56bc4b52132c0cd1e3a6
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 19:35:44 2017 +0200

    almost finished setting up the symfony demo case

commit 1a3c9ebfd428ba21a65dd9e2be34c6b3a2f88960
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 16:22:04 2017 +0200

    remove debug out

    remove echos

commit 70d937c18bae8b7baf4ed313c47f2001e8e43e1d
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 16:21:13 2017 +0200

    start with training case implementation

commit 414fd54cfe8b14500eb7663396cc4157d1c52d1d
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 14:34:27 2017 +0200

    improvements to db interface

commit e0b1a86dbed3377682b4057542809d343a3598e8
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 14:33:38 2017 +0200

    ignore *.swp

commit c9aa8cad0888d82753b32d6a4c0457b67bd2e81b
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 14:18:08 2017 +0200

    implement force, fix NGINX config

commit 6c61d14140e45552dabd45a13fad1844c9e84329
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 14:17:46 2017 +0200

    remove not required file

commit c1bec7398c130a288549a90ef1ed26bfe9d3fcc0
Author: Anatol Belski <ab@php.net>
Date:   Mon May 29 13:46:31 2017 +0200

    basic PHP setup and usable CLI

commit d2227d31799030334b0a635ea1fb0474dea23416
Author: Anatol Belski <ab@php.net>
Date:   Fri May 26 13:27:23 2017 +0200

    add license

commit f96743bd1a89d068c49954ac5e46a8e302e44d85
Author: Anatol Belski <ab@php.net>
Date:   Tue May 23 18:31:20 2017 +0200

    basic init/up/down for MariaDB and some bug fixes

commit 14bf57ceab9586e365ad43de2250629249f8a198
Author: Anatol Belski <ab@php.net>
Date:   Tue May 23 17:39:22 2017 +0200

    improve config handling, more on nginx management

commit 8c407130658ac56b2d360b664c35bb95f5ffb5ec
Author: Anatol Belski <ab@php.net>
Date:   Tue May 23 17:29:09 2017 +0200

    switch to json for internal conf

commit e744887d307e8e65a2666fd9baf1b94ae33f1e12
Author: Anatol Belski <ab@php.net>
Date:   Tue May 23 17:28:04 2017 +0200

    extend gitignore

commit 88dd8f0cd5928b25e8af919b61168056946b64b5
Author: Anatol Belski <ab@php.net>
Date:   Tue May 23 16:10:57 2017 +0200

    basic nginx init routines and expand on config

commit 0c4f660904370b3aa9d002118a8b923ffaa132e7
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 20:46:04 2017 +0200

    add unzip to fileops and some more refactoring

commit f1aeb9ac43dd817c0ac208714943162117329e3f
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 19:17:01 2017 +0200

    group ns

commit f92a4b45a58f6969fdb139278157ff5556cc9879
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 19:15:56 2017 +0200

    use curl for fetches

commit 09e01d62cb74aba6158943e0418c94f09e136248
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 17:58:55 2017 +0200

    fix branch name recognition when no cli opt passed

commit 50c54bdacc0bc0383ed5feb592bfc16092ffb173
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 17:22:50 2017 +0200

    simplify

commit 5e293210c678729c67c75ea4112f12832375bdf3
Author: Anatol Belski <ab@php.net>
Date:   Mon May 22 17:14:13 2017 +0200

    yet basic PGO stuff
2018-01-12 18:02:50 +01:00
Anatol Belski
7a054e9e6d Revert "Upgrade vswhere"
This reverts commit a6f819dd75.
2018-01-12 18:01:22 +01:00
Anatol Belski
a6f819dd75 Upgrade vswhere 2018-01-10 17:45:18 +01:00
Anatol Belski
b8b32aaa27 Avoid each() 2018-01-10 17:34:19 +01:00
Anatol Belski
dbeb065486 Use spl_autoload_register() 2018-01-10 17:33:51 +01:00
Anatol Belski
c2880591f3 Mention ConEmu 2017-11-24 10:34:24 +01:00
Anatol Belski
6911eacb83 Update example cmd 2017-11-24 10:32:22 +01:00
姚文强
218f23ab93 fix typo (#23)
Thanks :)
2017-11-24 10:31:19 +01:00
Anatol Belski
1684c7e2c7 Back to dev 2017-11-17 15:10:00 +01:00
Anatol Belski
fb396f33e6 Prepare 2.0.13 2017-11-17 15:09:22 +01:00
Anatol Belski
1deb33bebc Upgrade vswhere 2017-11-17 14:53:31 +01:00
Anatol Belski
d00bcf80d0 Upgrade bundled PHP 2017-11-17 14:44:40 +01:00
Anatol Belski
1d645c9faf Unset some tmp vars 2017-11-17 14:27:52 +01:00
Anatol Belski
c9ff81440a Note on unattended build 2017-11-17 14:09:21 +01:00
Anatol Belski
c3a4890b8a Check for Windows SDK 10.0 for VC14, too 2017-11-16 11:13:02 +01:00
Anatol Belski
ac53945a3f Pass nologo to vcvarsall.bat 2017-11-15 19:37:22 +01:00
Anatol Belski
c7ad0fd314 Unify EOL 2017-11-14 19:48:45 +01:00
johnstevenson
76ed6e3374 Ensure starter scripts keep the current directory
If a `source` directory is found in the User profile (via
%USERPROFILE%\Source) the VS 2017 Command Prompt script will change to
this directory in its clean-up routines.

This fix uses the VSCMD_START_DIR variable which is provided as an
escape-hatch for this behavior, in `..\core\vsdevcmd_end.bat`.
2017-11-14 19:46:55 +01:00
Anatol Belski
f3cbba7fc5 Update version in readme 2017-11-04 11:50:14 +01:00
Anatol Belski
1d4d208f4b Add comment 2017-11-03 23:30:01 +01:00
Anatol Belski
6711f1f6d1 Fix curl error handling 2017-11-02 12:57:44 +01:00
Anatol Belski
1ba1bf1dff Back to dev 2017-10-26 19:31:06 +02:00
Anatol Belski
1048a4d346 Prepare 2.0.12 2017-10-26 19:30:06 +02:00
Anatol Belski
ed4f2d50d0 Reflect re2c version 2017-10-26 12:51:30 +02:00
Anatol Belski
75124abf52 Note about fetching 2017-10-25 22:55:32 +02:00
Anatol Belski
58d2c1a009 Add note about UNIX flavors 2017-10-25 22:53:41 +02:00
Anatol Belski
dfdea742dc Reflect bison version 2017-10-25 21:00:01 +02:00
Anatol Belski
0553f3219f Rephrase 2017-10-25 20:14:23 +02:00
Anatol Belski
2cbe03f44c Back to dev 2017-10-18 17:41:15 +02:00
Anatol Belski
550407fb29 Prepare beta3 2017-10-18 17:40:27 +02:00
Anatol Belski
dd4844b6d2 Rebase MSYS2 DLLs 2017-10-18 15:02:53 +02:00
Anatol Belski
ae51b4e28f Turn back to dev 2017-10-16 17:11:18 +02:00
Anatol Belski
6705c85ebd Prepare 2.0.12beta2 2017-10-16 17:10:09 +02:00
Anatol Belski
8fd8187d28 Add missing DLLs 2017-10-16 17:07:19 +02:00
Anatol Belski
353b184487 Back to dev 2017-10-11 20:23:01 +02:00
Anatol Belski
9345164d3a Prepare 2.0.12beta1 2017-10-11 20:21:32 +02:00
Anatol Belski
d2b2d58f84 Upgrade vswhere 2017-10-11 09:14:30 +02:00
Anatol Belski
9da65f2386 Upgrade msys2 tools
- re2c is upgraded manually to 1.0.2
2017-10-10 11:20:18 +02:00
Anatol Belski
1f48f48b94 Back to dev 2017-09-15 23:01:39 +02:00
Anatol Belski
0cd8d902c0 2.0.11 2017-09-15 23:00:47 +02:00
Anatol Belski
c7c874e9b4 Improve messaging for locked dependency path 2017-09-15 10:47:22 +02:00
Anatol Belski
97112e4dd0 Refactor lock also wrt shared/exclusive 2017-09-15 10:36:13 +02:00
Anatol Belski
098f6457de Folds 2017-09-15 09:23:48 +02:00
Anatol Belski
a5afa11cff Integrate locking into the dep update process 2017-09-14 18:49:14 +02:00
Anatol Belski
6b58f91d9d Fix and improve lock class 2017-09-14 18:48:43 +02:00
Anatol Belski
bb5ff05cc5 Add locker class 2017-09-14 18:07:37 +02:00
Anatol Belski
4b51347c35 Lock while caching 2017-09-14 16:54:03 +02:00
Anatol Belski
7d48cafe29 Folds 2017-09-14 16:25:35 +02:00
Anatol Belski
d802183581 Adjust description 2017-09-05 12:45:08 +02:00
Anatol Belski
741063cdf1 Support branch recognition when working under dev package 2017-09-05 12:38:02 +02:00
Jerry
a97d0bd292 Fix Arch determintion 2017-09-01 15:52:35 +02:00
Anatol Belski
5507b37b7d Add pretty option 2017-08-29 10:46:39 +02:00
Anatol Belski
7c72855fd0 Rework dllmap script 2017-08-28 16:11:49 +02:00
Anatol Belski
b5829cd502 Note pwgen presence 2017-08-28 14:36:26 +02:00
Anatol Belski
de669c7610 Back to dev 2017-08-28 13:08:32 +02:00
Anatol Belski
f96fbeddab 2.0.10 2017-08-28 13:07:34 +02:00
Anatol Belski
ceececf83f Improve the pack command, show more info and translate the exit code 2017-08-28 13:05:18 +02:00
Anatol Belski
64c2ac973c Fix deps path recognition 2017-08-23 00:19:10 +02:00
Anatol Belski
79116d5051 add deps package command 2017-08-21 11:48:08 +02:00
Anatol Belski
c3bb9777bb reset errorlevel before tool run, set the current on exit 2017-08-21 10:49:42 +02:00
Anatol Belski
eae3aab2ae revert the deps path reset part and sync 2017-08-17 18:19:07 +02:00
Anatol Belski
e7e92b35d0 yet more path recognition variant 2017-08-17 16:33:32 +02:00
Anatol Belski
d158c3c032 add possibility to reevaluate the deps path 2017-08-17 16:17:47 +02:00
Anatol Belski
69fb69fd93 no realpath needed 2017-08-17 15:33:38 +02:00
Anatol Belski
aee165fe05 refactor dependency dir recognition 2017-08-17 14:06:01 +02:00
Anatol Belski
022333118e upgrade vswhere 2017-08-12 14:30:55 +02:00
Anatol Belski
821c0d7c73 extend .gitignore 2017-07-26 17:14:46 +02:00
Anatol Belski
7d72596e85 back to dev 2017-07-24 23:00:09 +02:00
Anatol Belski
2b317c62e1 prepare 2.0.9 2017-07-24 22:51:26 +02:00
Anatol Belski
61d589c424 sync with eol change 2017-07-24 11:07:16 +02:00
Anatol Belski
eaa6ff57fa add more file types for eol mitigation 2017-07-23 20:57:55 +02:00
Anatol Belski
5efd876bb3 extend redme 2017-07-23 20:55:09 +02:00
Dylan K. Taylor
0319dc061f add gitattributes 2017-07-23 20:41:19 +02:00
Anatol Belski
40fe451c8d add comment 2017-07-22 02:26:10 +02:00
Anatol Belski
55fddef1a3 back to dev 2017-07-20 21:57:07 +02:00
Anatol Belski
af769d9604 prepare 2.0.8 2017-07-20 21:56:22 +02:00
Anatol Belski
8e3d43905b Support also preview releases
But for now - only as a fallback if no other VS install could be found.
2017-07-13 11:15:38 +02:00
Anatol Belski
ebf3928220 upgrade bundled php 2017-07-12 15:51:42 +02:00
Anatol Belski
f96329c0fd back to dev 2017-07-10 21:39:46 +02:00
Anatol Belski
7cc831e6aa prepare 2.0.7 2017-07-10 21:38:56 +02:00
Anatol Belski
24e2464d8c improve branch name guessing 2017-07-10 12:02:17 +02:00
Anatol Belski
738abd255e fixed option handling, thanks Kalle 2017-07-08 18:55:06 +02:00
Anatol Belski
691d70fc09 upgrade to vswhere 2.0.2 2017-07-05 17:34:46 +02:00
Anatol Belski
412c512208 extend deps update comment 2017-06-29 00:02:19 +02:00
Anatol Belski
97a436c3fc task.exe commen 2017-06-28 23:54:56 +02:00
Anatol Belski
9e5e7e6c17 back to dev 2017-06-16 02:42:12 +02:00
Anatol Belski
e17b752c19 prepare 2.0.6 2017-06-16 02:40:35 +02:00
Jan-E
527b18189c Include CRT & ARCH in title
The command box has a title 'PHP SDK' now.
Make it descriptive like 'PHP SDK vc15 x86'
2017-06-16 02:38:27 +02:00
Anatol Belski
f4e3f68ce5 fix current arch setter 2017-06-16 02:34:57 +02:00
Anatol Belski
99efb73f17 back to dev 2017-06-05 20:40:43 +02:00
155 changed files with 28652 additions and 3641 deletions

7
.gitattributes vendored Normal file
View File

@@ -0,0 +1,7 @@
*.m4 text eol=lf
*.awk text eol=lf
*.c text eol=lf
*.h text eol=lf
*.php text eol=lf
*.json text eol=lf
*.md text eol=lf

5
.gitignore vendored
View File

@@ -4,6 +4,7 @@ php55
php56
php70
php71
php72
phpmaster
php
!lib/php
@@ -19,3 +20,7 @@ oracle
#pgo-build
#rmtools*
phpsdk-local.bat
pgo/work
!pgo/tpl/php
!lib/php/libsdk/SDK/Build/PGO/Server/PHP
*.swp

18
LICENSE
View File

@@ -1,9 +1,9 @@
Copyright 2017 Anatol Belski
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Copyright 2017-2018 Anatol Belski
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

269
README.md
View File

@@ -1,115 +1,154 @@
# PHP SDK
PHP SDK is a tool kit for Windows PHP builds
# License
The PHP SDK itself and the SDK own tools are licensed under the BSD 2-Clause license. With the usage of the other tools, you accept the respective licenses.
# Overview
The PHP SDK 2.0 is compatible with PHP 7.0 and above. The compatibility with [older versions](http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip "php-sdk-binary-tools-20110915.zip") is kept, also available from the [legacy branch](https://github.com/OSTC/php-sdk-binary-tools/tree/legacy). The toolset was significantly revamped. Newer tools are now available, better workflows are now possible. The toolset consists on a mix of the hand written scripts, selected MSYS2 parts and standalone programs.
# Requirements
- `Visual C++ 2015` or `Visual C++ 2017` must be installed prior SDK usage
- if `Cygwin` is installed, please read notes in the pitfalls section
- if a 64-bit build is intended, a 64-bit system is required. Cross compilation of 64-bit on 32-bit system is not supported at the moment
- The PHP SDK was successfully tested on Windows 7 or later, earlier versions might work but are not recommended
# Tools
All the tools included are either scripts or 32-bit binaries. They are therefore runable on any of x86 or x64 supported Windows system.
## SDK
- starter scripts, named phpsdk-&lt;crt&gt;-&lt;arch&gt;.bat
- `phpsdk_buildtree` - initialize the development filesystem structure
- `phpsdk_deps` - handle dependency libraries
- `phpsdk_version` - show SDK version
- `phpsdk_dllmap` - create a JSON listing of DLLs contained in zip files
- `task.exe` - wrapper to hide the given command line
## Other tools
- `bison` 3.0.2, `re2c` 0.15.3, `lemon`
- `awk`, `gawk`, `sed`, `grep`
- `diff`, `diff3`, `patch`
- `md5sum`, `sha1sum`, `sha224sum`, `sha256sum`, `sha384sum`, `sha512sum`
- `7za`, `zip`, `unzip`, `unzipsfx`
- `wget`
## Optional, not included
These are not included with the PHP SDK, but might be useful. While Visual C++ is the only required, the others might enable some additional functionality. Care yourself about making them available on your system, if relevant.
- `Git` - useful for PHP source management
- `Cppcheck` - used for static analysis
- `clang` - useful for experimental builds and for static analysis
- `ICC` - useful for experimental builds
# Usage
The PHP SDK should be unzipped into the shortest possible path, preferrably somewhere near the drive root.
Usually, the first step to start the PHP SDK is by invoking one of the suitable starter scripts. This automatically puts the console on the correct environment relevant for the desired PHP build configuration.
It is not required to hold the source in the PHP SDK directory. It could be useful, for example, to simplify the SDK updates.
## Basic usage example
- `git clone https://github.com/OSTC/php-sdk-binary-tools.git c:\php-sdk`
- `cd c:\php-sdk`
- `git checkout php-sdk-2.0.0` or later
- invoke `phpsdk-vc15-x64.bat`
- `phpsdk_buildtree phpmaster`
- `git clone https://github.com/php/php-src.git && cd php-src`, or fetch a zipball
- `phpsdk_deps --update --branch master`
- do the build, eg. `buildconf && configure --enable-cli && nmake`
More extensive documentation can be found on the [wiki](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2 "PHP wiki page").
## The old way
- `git clone https://github.com/OSTC/php-sdk-binary-tools.git c:\php-sdk`
- follow the instructions on the PHP [wiki page](https://wiki.php.net/internals/windows/stepbystepbuild "PHP wiki page")
# Customizing
## Custom environment setup
A sript called phpsdk-local.bat has to be put into the PHP SDK root. If present, it will be automatically picked up by the starter script. A template for such a script is included with the PHP SDK. This allows to automatically meet any required preparations, that are not foreseen by the standard PHP SDK startup. Be careful while creating your own phpsdk-local. It's your responsibility to ensure the regular PHP SDK startup isn't broken after phpsdk-local.bat was injected into the startup sequence.
## Console emulator integration
The starter scripts can be also easy integrated with the consoles other than standard cmd.exe. For the reference, here's an example ConEmu task
`C:\php-sdk\phpsdk-vc14-x64.bat -cur_console:d:C:\php-sdk\php70\vc14\x64\php-src`
## Unattended builds
An elementary functionality to run unattended builds is included. See an example on how to setup a simple unattended build task in the doc directory.
# Upgrading
- backup phpsdk-local.bat
- backup the source trees and any other custom files in the PHP SDK root, if any present
- move the PHP SDK folder into trash
- download, unpack and the new PHP SDK version under the same path
- move the custom files back in their respective places
If the PHP SDK is kept as a git checkout, merely what is needed instead is to git fetch and to checkout an updated git tag.
# Extending
The SDK tools are based on the KISS principle and should be kept so. Basic tools are implemented as simple batch script. The minimalistic `PHP` is available for internal SDK purposes. It can be used, if more complexity is required. If you have an idea for some useful tool or workflow, please open a ticket or PR, so it can be discussed, implemented and added to the SDK. By contributing an implementation, you should also accept the SDK license.
# Pitfalls
- SDK or PHP sources put into paths including spaces might cause issue.
- SDK or PHP sources put into too long paths, will cause an issue.
- If Cygwin is installed, it might cause issues. If it's unavoidable, to have Cygwin on the same machine, ensure SDK preceeds it on the PATH.
- Tools, based on MSYS2, only accept paths with forward slashes.
- Both Visual C++ toolset and the Windows SDK components have to be installed for the PHP SDK to work properly.
- The VC++ toolset is still requried, even if another compiler, fe. clang, is intended to be used.
# PHP SDK
PHP SDK is a tool kit for Windows PHP builds.
# License
The PHP SDK itself and the SDK own tools and code are licensed under the BSD 2-Clause license. With the usage of the other tools, you accept the respective licenses.
# Overview
The PHP SDK 2.0+ is compatible with PHP 7.0 and above. The compatibility with [older versions](http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip "php-sdk-binary-tools-20110915.zip") is kept, also available from the [legacy branch](https://github.com/Microsoft/php-sdk-binary-tools/tree/legacy). The toolset was significantly revamped. Newer tools are now available, better workflows are now possible. The toolset consists on a mix of the hand written scripts, selected MSYS2 parts and standalone programs.
# Requirements
- `Visual C++ 2015` or `Visual C++ 2017` must be installed prior SDK usage
- if `Cygwin` is installed, please read notes in the pitfalls section
- if a 64-bit build is intended, a 64-bit system is required. Cross compilation of 64-bit on 32-bit system is not supported at the moment
- The PHP SDK was successfully tested on Windows 7 or later, earlier versions might work but are not recommended
# Tools
All the tools included are either scripts or 32-bit binaries. They are therefore runable on any of x86 or x64 supported Windows system.
## SDK
- starter scripts, named phpsdk-&lt;crt&gt;-&lt;arch&gt;.bat
- `phpsdk_buildtree` - initialize the development filesystem structure
- `phpsdk_deps` - handle dependency libraries
- `phpsdk_dllmap` - create a JSON listing of DLLs contained in zip files
- `phpsdk_pgo` - run PGO training
- `phpsdk_version` - show SDK version
- `task.exe` - wrapper to hide the given command line
## Other tools
- `bison` 3.0.4, `re2c` 1.0.3, `lemon`
- `awk`, `gawk`, `sed`, `grep`
- `diff`, `diff3`, `patch`
- `md5sum`, `sha1sum`, `sha224sum`, `sha256sum`, `sha384sum`, `sha512sum`
- `7za`, `zip`, `unzip`, `unzipsfx`
- `wget`, `pwgen`
## Optional, not included
These are not included with the PHP SDK, but might be useful. While Visual C++ is the only required, the others might enable some additional functionality. Care yourself about making them available on your system, if relevant.
- `Git` - useful for PHP source management
- `Cppcheck` - used for static analysis
- `clang` - useful for experimental builds and for static analysis
- `ICC` - useful for experimental builds
- `ConEmu` - console emulator with tabs and more
# Usage
The PHP SDK should be unzipped into the shortest possible path, preferrably somewhere near the drive root.
Usually, the first step to start the PHP SDK is by invoking one of the suitable starter scripts. This automatically puts the console on the correct environment relevant for the desired PHP build configuration.
It is not required to hold the source in the PHP SDK directory. It could be useful, for example, to simplify the SDK updates.
## Basic usage example
- `git clone https://github.com/Microsoft/php-sdk-binary-tools.git c:\php-sdk`
- `cd c:\php-sdk`
- `git checkout php-sdk-2.0.12` or later
- invoke `phpsdk-vc15-x64.bat`
- `phpsdk_buildtree phpmaster`
- `git clone https://github.com/php/php-src.git && cd php-src`, or fetch a zipball
- `phpsdk_deps --update --branch master`, use `phpsdk_deps --update --branch X.Y` for a non master branch
- do the build, eg. `buildconf && configure --enable-cli && nmake`
More extensive documentation can be found on the [wiki](https://wiki.php.net/internals/windows/stepbystepbuild_sdk_2 "PHP wiki page").
## The old way
- `git clone https://github.com/Microsoft/php-sdk-binary-tools.git c:\php-sdk`
- follow the instructions on the PHP [wiki page](https://wiki.php.net/internals/windows/stepbystepbuild "PHP wiki page")
# Customizing
## Custom environment setup
A script called phpsdk-local.bat has to be put into the PHP SDK root. If present, it will be automatically picked up by the starter script. A template for such a script is included with the PHP SDK. This allows to automatically meet any required preparations, that are not foreseen by the standard PHP SDK startup. Be careful while creating your own phpsdk-local. It's your responsibility to ensure the regular PHP SDK startup isn't broken after phpsdk-local.bat was injected into the startup sequence.
## Console emulator integration
The starter scripts can be also easy integrated with the consoles other than standard cmd.exe. For the reference, here's an example ConEmu task
`C:\php-sdk\phpsdk-vc15-x64.bat -cur_console:d:C:\php-sdk\php72\vc15\x64\php-src`
## Unattended builds
An elementary functionality to run unattended builds is included. See an example on how to setup a simple unattended build task in the doc directory.
Be aware, that starter scripts always start a new shell. Scripts intended to run as a task need to be passed with `-t` argument to a starter script.
# Upgrading
- backup phpsdk-local.bat
- backup the source trees and any other custom files in the PHP SDK root, if any present
- move the PHP SDK folder into trash
- download, unpack and the new PHP SDK version under the same path
- move the custom files back in their respective places
If the PHP SDK is kept as a git checkout, merely what is needed instead is to git fetch and to checkout an updated git tag.
# Extending
The SDK tools are based on the KISS principle and should be kept so. Basic tools are implemented as simple batch script. The minimalistic `PHP` is available for internal SDK purposes. It can be used, if more complexity is required. A suitable PHP binary is bound with the PHP SDK. If you have an idea for some useful tool or workflow, please open a ticket or PR, so it can be discussed, implemented and added to the SDK. By contributing an implementation, you should also accept the SDK license.
# PGO
As of the version 2.1.0, the SDK includes a tool for the [PGO](https://docs.microsoft.com/en-us/cpp/build/reference/profile-guided-optimizations) optimization. Several training cases are included by default, which are based on the real life opensource applications. The PGO optimization can give an overall speedup up to 30%. The work on adding more training scenarios for the widely used opensource apps is ongoing. If you have a training scenario to share, please create a PR to this repo. Any new training cases are thoroughly validated through the extensive performance tests.
## Preparing PGO training environment
- the pgo folder in the SDK root dir contains templates and scenarios for PGO training
- adjust and execute [doc/phpsdk_pgo_prep_elevated.bat.example](doc/phpsdk_pgo_prep_elevated.bat.example) to open ports required for PHP SDK training servers
- run `phpsdk_pgo --init`
## Creating PGO build
- compile PHP configured using `--enable-pgi`
- run `phpsdk_pgo --train`
- run `nmake clean-pgo`
- rebuild PHP `--with-pgo`
## Adding custom PGO training scenario
A custom scenario can be used to produce a custom PHP binary dedicated to an arbitrary application.
The existing training cases can be found in [pgo/cases](pgo/cases). Assumed the case would be named `myapp`, the general steps to setup were
- create the case directory under `pgo/cases/myapp`
- create `pgo/cases/myapp/phpsdk_pgo.json` with the necessary definitions
- create `pgo/cases/myapp/nginx.partial.conf` with a partial NGINX template
- create `pgo/cases/myapp/TrainingCaseHandler.php` with a class as defined in the [interface](lib/php/libsdk/SDK/Build/PGO/Interfaces/TrainingCase.php)
After a training case is implemented and put under `pgo/cases`, the work environment needs to be reinitialized. The tool puts all the training data and necessary applications under `pgo/work`. Rename or remove that directory and rerun `phpsdk_pgo --init`.
To skip a training case, add a file named `inactive` into the case folder.
# Pitfalls
- SDK or PHP sources put into paths including spaces might cause issue.
- SDK or PHP sources put into too long paths, will cause an issue.
- If Cygwin, MSYS2 or MinGW flavors are exposed in global PATH, it might cause issues. If it's unavoidable, ensure SDK preceeds it on the PATH.
- When fetching the binary SDK from git, git `core.autocrlf` configuration directive set to `false` is recommended.
- Tools, based on MSYS2, only accept paths with forward slashes.
- Both Visual C++ toolset and the Windows SDK components have to be installed for the PHP SDK to work properly.
- The VC++ toolset is still requried, even if another compiler, fe. clang, is intended to be used.
- `task.exe` is not a console application, some systems might not propagate exit code except the batch is explicitly run from `cmd /c`, etc.
- `7za` should be prefered over `unzip` and `zip` for compatibility reasons.

View File

@@ -1 +1 @@
2.0.5
2.1.3

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -7,6 +7,8 @@ IF "%2" EQU "" SET _=%CD%\%1
rem if we're in the starter script shell, create the only struct that corresponds to the current env
rem otherwise - retain the old behavior, create structs for all the known build combinations and don't cd
cmd /c "exit /b 0"
if "%PHP_SDK_ARCH%" NEQ "" (
if "%PHP_SDK_VC%" NEQ "" (
MD %_%\%PHP_SDK_VC%\%PHP_SDK_ARCH%\deps\bin
@@ -35,3 +37,5 @@ echo phpsdk_buildtree ^<nameofthetree^> [PATH]
echo Create the common directory structure used by the PHP SDK
:EXIT
exit /b %errorlevel%

View File

@@ -1,5 +1,7 @@
@echo off
cmd /c "exit /b 0"
if "%PHP_SDK_PHP_CMD%"=="" (
call %~dp0phpsdk_setvars.bat
if "!PHP_SDK_PHP_CMD!"=="" (
@@ -10,5 +12,5 @@ if "%PHP_SDK_PHP_CMD%"=="" (
call %PHP_SDK_PHP_CMD% %PHP_SDK_BIN_PATH%\phpsdk_deps.php %*
exit /b
exit /b %errorlevel%

View File

@@ -1,10 +1,10 @@
<?php
include dirname(__FILE__) . "/../lib/php/libsdk/autoload.php";
include dirname(__FILE__) . "/../lib/php/autoload.php";
use SDK\{Config, Exception};
$sopt = "s:cuhb:a:d:t:fn";
$sopt = "s:cuhb:a:d:t:fnp";
$lopt = array(
"branch:",
"update",
@@ -16,6 +16,7 @@ $lopt = array(
"deps:",
"force",
"no-backup",
"pack",
);
$cmd = NULL;
@@ -28,6 +29,8 @@ $backup = true;
try {
$branch = NULL;
$opt = getopt($sopt, $lopt);
foreach ($opt as $name => $val) {
switch ($name) {
@@ -42,7 +45,9 @@ try {
case "b":
case "branch":
Config::setCurrentBranchName($val);
/* Branch config depends on other information. We can set it
right away, because the option order can't be guaranteed. */
$branch = $val;
break;
case "s":
@@ -83,9 +88,22 @@ try {
case "no-backup":
$backup = false;
break;
case "p":
case "pack":
$cmd = "pack";
break;
}
}
if (NULL == $branch) {
$branch = Config::guessCurrentBranchName();
if (NULL == $branch) {
throw new Exception("Couldn't determine current branch name, expect an explicit input.");
}
}
Config::setCurrentBranchName($branch);
if (NULL === $cmd) {
usage();
}
@@ -145,6 +163,16 @@ try {
$dm->performUpdate($msg, $force, $backup);
msg($msg);
break;
case "pack":
$path_to_pack = Config::getDepsLocalPath();
$pack_path = dirname($path_to_pack) . DIRECTORY_SEPARATOR . "deps-$branch-$branch_data[crt]-$branch_data[arch].7z";
print "Packaging '$path_to_pack' as '$pack_path'.\n\n";
if ($force && is_file($pack_path)) {
unlink($pack_path);
}
system("7za a $pack_path $path_to_pack", $st);
exit((int)$st);
break;
}
} catch (Throwable $e) {
@@ -159,13 +187,14 @@ function usage(int $code = -1)
echo "PHP SDK dependency handling tool.", PHP_EOL;
echo "Usage: ", PHP_EOL, PHP_EOL;
echo "Configuration:", PHP_EOL;
echo " -b --branch Branch name, eg. 7.0, 7.1, etc. If omited, CWD is used to guess.", PHP_EOL;
echo " -b --branch Branch name, eg. 7.0, 7.1, etc. If omited, several guess methods apply.", PHP_EOL;
echo " -a --arch Architecture, x86 or x64. If omited, cl.exe is used to guess.", PHP_EOL;
echo " -t --crt CRT, marked by the corresponding VC++ version, eg. vc11, vc14, etc.", PHP_EOL;
echo " -s --stability One of stable or staging.", PHP_EOL, PHP_EOL;
echo "Commands:", PHP_EOL;
echo " -c --check Check for dependency updates. If updates are available, the exit code is set to 7.", PHP_EOL;
echo " -u --update Update dependencies. If deps directory already exists, backup copy is created automatically.", PHP_EOL, PHP_EOL;
echo " -u --update Update dependencies. If deps directory already exists, backup copy is created automatically.", PHP_EOL;
echo " -p --pack Archive the dependency directory.", PHP_EOL, PHP_EOL;
echo "Misc:", PHP_EOL;
echo " -d --deps Path to the dependencies directory. If omited, CWD is used to guess.", PHP_EOL;
echo " -f --force Force the operation even if there are no upgrades available.", PHP_EOL;

View File

@@ -1,5 +1,7 @@
@echo off
cmd /c "exit /b 0"
if "%PHP_SDK_PHP_CMD%"=="" (
call %~dp0phpsdk_setvars.bat
if "!PHP_SDK_PHP_CMD!"=="" (
@@ -10,5 +12,5 @@ if "%PHP_SDK_PHP_CMD%"=="" (
call %PHP_SDK_PHP_CMD% %PHP_SDK_BIN_PATH%\phpsdk_dllmap.php %*
exit /b
exit /b %errorlevel%

View File

@@ -6,7 +6,7 @@
- create mappings between dll filename and zip filename
Usage:
php dllmap.php path0 [ path1 ... ] > dllmapping.json
php dllmap.php [--pretty] path0 [ path1 ... ] > dllmapping.json
*/
@@ -20,8 +20,25 @@
"C:\\tmp\\libs",
);*/
$sopt = "p";
$lopt = array(
"pretty",
);
$flags = 0;
$opt = getopt($sopt, $lopt);
foreach ($opt as $name => $val) {
switch ($name) {
case "p":
case "pretty":
$flags = JSON_PRETTY_PRINT;
break;
}
}
$dirs = array();
foreach (array_slice($_SERVER["argv"], 1) as $item) {
foreach (array_slice($_SERVER["argv"], (0 == $flags ? 1 : 2)) as $item) {
if (file_exists($item) && is_dir($item)) {
$dirs[] = $item;
}
@@ -32,26 +49,7 @@ if (empty($dirs)) {
die;
}
$out = array(
"vc9" => array(
"x86" => array(),
"x64" => array(),
),
"vc11" => array(
"x86" => array(),
"x64" => array(),
),
"vc12" => array(
"x86" => array(),
"x64" => array(),
),
"vc14" => array(
"x86" => array(),
"x64" => array(),
),
);
$out = array();
foreach ($dirs as $path) {
$dir = new DirectoryIterator($path);
@@ -74,6 +72,13 @@ foreach ($dirs as $path) {
$crt = $m[1];
$arch = $m[2];
if (!isset($out[$crt])) {
$out[$crt] = array();
}
if (!isset($out[$crt][$arch])) {
$out[$crt][$arch] = array();
}
$zip = new ZipArchive();
$zip->open($pathname);
@@ -100,7 +105,7 @@ foreach ($dirs as $path) {
}
}
echo json_encode($out);
echo json_encode($out, $flags);
/*
* Local variables:

View File

@@ -5,6 +5,8 @@ if "%PHP_SDK_OS_ARCH%"=="" (
exit /b 3
)
cmd /c "exit /b 0"
echo.
call %PHP_SDK_BIN_PATH%\phpsdk_version.bat
@@ -26,5 +28,5 @@ echo Visual C++: %PHP_SDK_VC_NUM%
echo PHP-SDK path: %PHP_SDK_ROOT_PATH%
exit /b
exit /b %errorlevel%

14
bin/phpsdk_pgo.bat Normal file
View File

@@ -0,0 +1,14 @@
@echo off
if "%PHP_SDK_PHP_CMD%"=="" (
call %~dp0phpsdk_setvars.bat
if "!PHP_SDK_PHP_CMD!"=="" (
echo PHP SDK is not setup
exit /b 3
)
)
cmd /c %PHP_SDK_PHP_CMD% %PHP_SDK_BIN_PATH%\phpsdk_pgo.php %*
exit /b %errorlevel%

127
bin/phpsdk_pgo.php Normal file
View File

@@ -0,0 +1,127 @@
<?php
include dirname(__FILE__) . "/../lib/php/autoload.php";
use SDK\Config;
use SDK\Exception;
use SDK\Build\PGO\Controller;
$sopt = "itudhs:fr";
$lopt = array("init", "train", "up", "down", "help", "scenario:", "force", "ready");
$cmd = NULL;
/* TODO For now we simply check the current php build, this could be extended to take arbitrary binaries. */
$deps_root = NULL;
$php_root = NULL;
$scenario = NULL;
$force = false;
try {
$opt = getopt($sopt, $lopt);
foreach ($opt as $name => $val) {
switch ($name) {
case "i":
case "init":
$cmd = "init";
break;
case "ready":
$cmd = "check_init";
break;
case "t":
case "train":
$cmd = "train";
break;
case "u":
case "up":
$cmd = "up";
break;
case "d":
case "down":
$cmd = "down";
break;
case "s":
case "scenario":
$scenario = $val;
break;
case "f":
case "force":
$force = true;
break;
case "h": case "help":
usage(0);
break;
}
}
if (NULL === $cmd) {
usage();
}
$deps_root = Config::getDepsLocalPath();
if ("check_init" != $cmd) {
/* XXX Need these checks for more safety, as long as the dist zipballs are not supported. */
if (!file_exists("Makefile")) {
throw new Exception("Makefile not found. Arbitrary php snapshots are not supported yet, switch to the php source dir.");
}
if (preg_match(",BUILD_DIR=(.+),", file_get_contents("Makefile"), $m)) {
$php_root = trim($m[1]);
}
if (!$php_root || !file_exists($php_root)) {
throw new Exception("Invalid php root dir encountered '$php_root'.");
}
}
$controller = new Controller($cmd, $scenario);
$controller->handle($force);
if ("check_init" == $cmd) {
/* 0 for success, fail otherwise. */
$ret = ($controller->isInitialized() === false);
exit((int)$ret);
}
/*$env = getenv();
$env["PATH"] = $deps_root . DIRECTORY_SEPARATOR . "bin;" . $env["PATH"];
$php = $php_root . DIRECTORY_SEPARATOR . "php.exe";
$php = $php_root . DIRECTORY_SEPARATOR . "php.exe";*/
} catch (Throwable $e) {
throw $e;
exit(3);
}
function usage(int $code = -1)
{
echo "PHP SDK PGO training tool.", PHP_EOL;
echo "Usage: ", PHP_EOL, PHP_EOL;
echo "Commands:", PHP_EOL;
echo " -i --init Initialize training environment.", PHP_EOL;
echo " -t --train Run training. This involves startup, training and shutdown.", PHP_EOL;
echo " -u --up Startup training environment.", PHP_EOL;
echo " -d --down Shutdown training environment.", PHP_EOL;
echo " -f --force Force requested operation. Not every option can be forced.", PHP_EOL;
echo " -s --scenario Run training with a specified scenario.", PHP_EOL;
/*echo " -p --php-root PHP binary to train.", PHP_EOL;*/
$code = -1 == $code ? 0 : $code;
exit($code);
}
function msg(string $s, int $code = 0) {
echo $s, PHP_EOL;
exit($code);
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/

View File

@@ -13,6 +13,8 @@ if "%1"=="-h" goto :help
if "%1"=="--help" goto :help
if "%2"=="" goto :help
cmd /c "exit /b 0"
set PHP_SDK_VC=%1
if /i not "%PHP_SDK_VC:~0,2%"=="vc" (
:malformed_vc_string
@@ -80,11 +82,15 @@ if 15 gtr %PHP_SDK_VC_NUM% (
rem vc15 support only for now, could parse out and pass on later
for /f "tokens=1* delims=: " %%a in ('%~dp0\vswhere -nologo -version %PHP_SDK_VC_NUM% -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath -format text') do set PHP_SDK_VC_DIR=%%b\VC
if not exist "!PHP_SDK_VC_DIR!" (
for /f "tokens=1* delims=: " %%a in ('%~dp0\vswhere -nologo -version %PHP_SDK_VC_NUM% -products Microsoft.VisualStudio.Product.BuildTools -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath -format text') do set PHP_SDK_VC_DIR=%%b\VC
if not exist "!PHP_SDK_VC_DIR!" (
echo Could not determine '%PHP_SDK_VC%' directory
goto out_error;
)
for /f "tokens=1* delims=: " %%a in ('%~dp0\vswhere -nologo -version %PHP_SDK_VC_NUM% -products Microsoft.VisualStudio.Product.BuildTools -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath -format text') do set PHP_SDK_VC_DIR=%%b\VC
if not exist "!PHP_SDK_VC_DIR!" (
rem check for a preview release
for /f "tokens=1* delims=: " %%a in ('%~dp0\vswhere -nologo -version %PHP_SDK_VC_NUM% -prerelease -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath -format text') do set PHP_SDK_VC_DIR=%%b\VC
if not exist "!PHP_SDK_VC_DIR!" (
echo Could not determine '%PHP_SDK_VC%' directory
goto out_error;
)
)
)
set VSCMD_ARG_no_logo=nologo
)
@@ -92,6 +98,21 @@ set TMPKEY=
if 15 gtr %PHP_SDK_VC_NUM% (
rem get sdk dir
rem if 10.0 is available, it's ok
if /i "%PHP_SDK_OS_ARCH%"=="x64" (
set TMPKEY=HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0
) else (
set TMPKEY=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0
)
for /f "tokens=2*" %%a in ('reg query "!TMPKEY!" /v InstallationFolder') do (
for /f "tokens=2*" %%c in ('reg query "!TMPKEY!" /v ProductVersion') do (
if exist "%%bInclude\%%d.0\um\Windows.h" (
goto got_sdk
)
)
)
rem Otherwise 8.1 should be available anyway
if /i "%PHP_SDK_OS_ARCH%"=="x64" (
set TMPKEY=HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.1
) else (
@@ -99,13 +120,13 @@ if 15 gtr %PHP_SDK_VC_NUM% (
)
for /f "tokens=2*" %%a in ('reg query "!TMPKEY!" /v InstallationFolder') do (
if exist "%%b\Include\um\Windows.h" (
set PHP_SDK_WIN_SDK_DIR=%%b
goto got_sdk
)
)
if not defined PHP_SDK_WIN_SDK_DIR (
echo Windows SDK not found.
goto out_error;
)
echo Windows SDK not found.
goto out_error;
:got_sdk
set TMPKEY=
)

View File

@@ -1,5 +1,7 @@
@echo off
cmd /c "exit /b 0"
rem Add necessary dirs to the path
set PHP_SDK_BIN_PATH=%~dp0
@@ -15,5 +17,5 @@ set PHP_SDK_PHP_CMD=%PHP_SDK_BIN_PATH%\php\do_php.bat
set PATH=%PHP_SDK_BIN_PATH%;%PHP_SDK_MSYS2_PATH%;%PATH%
exit /b
exit /b %errorlevel%

View File

@@ -1,5 +1,7 @@
@echo off
cmd /c "exit /b 0"
if "%PHP_SDK_PHP_CMD%"=="" (
call %~dp0phpsdk_setvars.bat
if "!PHP_SDK_PHP_CMD!"=="" (
@@ -10,5 +12,5 @@ if "%PHP_SDK_PHP_CMD%"=="" (
%PHP_SDK_PHP_CMD% -r "echo 'PHP SDK ' . file_get_contents(getenv('PHP_SDK_ROOT_PATH') . '\\VERSION');"
exit /b
exit /b %errorlevel%

Binary file not shown.

View File

@@ -1,9 +1,5 @@
@echo off
rem edit if PGO scripts are present and are to be used
rem set PHP_SDK_PGO_TOOLS_ROOT_PATH=%PHP_SDK_ROOT_PATH%\pgo
rem set PATH=%PHP_SDK_PGO_TOOLS_ROOT_PATH%\bin;%PATH%
set PGSQL_TEST_CONNSTR=host=127.0.0.1 dbname=test port=5432 user=test password=test
set PDO_PGSQL_TEST_DSN=pgsql:host=127.0.0.1 port=5432 dbname=test user=test password=test

View File

@@ -0,0 +1,47 @@
@echo off
rem These are default ports for the servers used for the training. If these
rem ports are changed in the config templates, the commands have to be
rem adjusted as well. New servers have to be added here as well. Run this
rem file on the elevated shell before starting the PGO environment setup
rem using the relevant port numbers, especially for unattended PGO builds.
rem We add opens inbound ports from the default PGO config templates and
rem and the one increment by 1, just co cover a simple case the port number
rem was incremented by the auto configuration.
rem
rem Alternatively, the firewall can be disabled on the build host.
rem The commands to disable\enable firewall are
rem netsh advfirewall set allprofiles state on
rem netsh advfirewall set allprofiles state off
@echo on
rem NGINX
netsh advfirewall firewall add rule name="NGINX for PGO" dir=in action=allow program="C:\php-snap-build\php-sdk\pgo\work\server\nginx\nginx.exe" profile=private
for \l %%p in (8081, 1, 8091) do (
netsh advfirewall firewall add rule name="Open Port %%p for PHP PGO" dir=in action=allow protocol=TCP localport=%%p profile=private
netsh advfirewall firewall add rule name="Open Port %%p for PHP PGO" dir=in action=allow protocol=UDP localport=%%p profile=private
)
netsh advfirewall firewall add rule name="Open Port 80 for PHP PGO" dir=in action=allow protocol=TCP localport=80 profile=private
netsh advfirewall firewall add rule name="Open Port 80 for PHP PGO" dir=in action=allow protocol=UDP localport=80 profile=private
rem MariaDB
netsh advfirewall firewall add rule name="MariaDB for PGO" dir=in action=allow program="c:\php-snap-build\php-sdk\pgo\work\server\mariadb\bin\mysqld.exe" profile=private
netsh advfirewall firewall add rule name="Open Port 3307 for PHP PGO" dir=in action=allow protocol=TCP localport=3307 profile=private
netsh advfirewall firewall add rule name="Open Port 3307 for PHP PGO" dir=in action=allow protocol=UDP localport=3307 profile=private
netsh advfirewall firewall add rule name="Open Port 3308 for PHP PGO" dir=in action=allow protocol=TCP localport=3308 profile=private
netsh advfirewall firewall add rule name="Open Port 3308 for PHP PGO" dir=in action=allow protocol=UDP localport=3308 profile=private
rem Postgres
netsh advfirewall firewall add rule name="Open Port 5434 for PHP PGO" dir=in action=allow protocol=TCP localport=5434 profile=private
netsh advfirewall firewall add rule name="Open Port 5434 for PHP PGO" dir=in action=allow protocol=UDP localport=5434 profile=private
netsh advfirewall firewall add rule name="Open Port 5435 for PHP PGO" dir=in action=allow protocol=TCP localport=5435 profile=private
netsh advfirewall firewall add rule name="Open Port 5435 for PHP PGO" dir=in action=allow protocol=UDP localport=5435 profile=private
rem PHP
netsh advfirewall firewall add rule name="Open Port 9001 for PHP PGO" dir=in action=allow protocol=TCP localport=9001 profile=private
netsh advfirewall firewall add rule name="Open Port 9001 for PHP PGO" dir=in action=allow protocol=UDP localport=9001 profile=private
netsh advfirewall firewall add rule name="Open Port 9002 for PHP PGO" dir=in action=allow protocol=TCP localport=9002 profile=private
netsh advfirewall firewall add rule name="Open Port 9002 for PHP PGO" dir=in action=allow protocol=UDP localport=9002 profile=private

View File

@@ -3,12 +3,12 @@ rem Task batch example.
rem Create a task, put an action with the following data:
rem Action: start a program
rem Program/script: C:\php-sdk\bin\task.exe
rem Add arguments: "C:\php-sdk\phpsdk-starter.bat -c vc14 -a x64 -t C:\php-sdk\unattended-build-task.bat"
rem Add arguments: "C:\php-sdk\phpsdk-starter.bat -c vc15 -a x64 -t C:\php-sdk\unattended-build-task.bat"
rem Run the task
set LOG_NAME=%PHP_SDK_VC%-%PHP_SDK_ARCH%-task.log
pushd C:\php-sdk\php70\vc14\x64\php-src
pushd C:\php-sdk\php72\vc14\x64\php-src
git pull --rebase > %LOG_NAME% 2>&1

26
lib/php/autoload.php Normal file
View File

@@ -0,0 +1,26 @@
<?php
spl_autoload_register(function($name) {
$fl = dirname(__FILE__) . DIRECTORY_SEPARATOR . "libsdk" . DIRECTORY_SEPARATOR . $name . ".php";
if (file_exists($fl)) {
require_once $fl;
}
});
spl_autoload_register(function($name) {
$fl = getenv("PHP_SDK_ROOT_PATH") . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "cases" . DIRECTORY_SEPARATOR . $name . ".php";
if (file_exists($fl)) {
require_once $fl;
}
});
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/

View File

@@ -15,12 +15,13 @@ class Fetcher
protected $series;
public function __construct(string $host, int $port, string $arch = NULL, string $stability = NULL, Series $series = NULL)
public function __construct(string $host, int $port, string $scheme = "https", string $arch = NULL, string $stability = NULL, Series $series = NULL)
{/*{{{*/
$this->stability = $stability;
$this->arch = $arch;
$this->host = $host;
$this->port = $port;
$this->scheme = $scheme;
}/*}}}*/
public function getSeries() : Series
@@ -35,11 +36,23 @@ class Fetcher
/* TODO more robust implementation. */
/* TODO implement indicator. */
public function getByUri($uri) : string
public function getByUri(string $uri, int $retries = 3) : string
{/*{{{*/
$url = "http://{$this->host}:{$this->port}$uri";
$url = "{$this->scheme}://{$this->host}:{$this->port}$uri";
$ret = false;
return $this->download($url);
retry:
try {
$ret = $this->download($url);
} catch (Exception $e) {
if ($retries > 0) {
sleep(1);
$retries--;
goto retry;
}
}
return $ret;
}/*}}}*/
/*protected function fetch($uri) : string

View File

@@ -2,7 +2,7 @@
namespace SDK\Build\Dependency;
use SDK\{Config, Cache, Exception, FileOps};
use SDK\{Config, Cache, Exception, FileOps, Lock};
class Manager
{
@@ -13,6 +13,7 @@ class Manager
protected $path;
protected $series;
protected $fetcher;
protected $updatesFlag = NULL;
public function __construct(string $path, string $stability, string $arch)
{/*{{{*/
@@ -23,7 +24,8 @@ class Manager
$host = Config::getDepsHost();
$port = Config::getDepsPort();
$fetcher = new Fetcher($host, $port, $this->arch, $this->stability);
$scheme = Config::getDepsUriScheme();
$fetcher = new Fetcher($host, $port, $scheme, $this->arch, $this->stability);
$series = new Series($this->stability, $this->arch, $this->cache, NULL);
$fetcher->setSeries($series);
$series->setFetcher($fetcher);
@@ -39,7 +41,12 @@ class Manager
public function updatesAvailable() : bool
{/*{{{*/
return $this->series->updatesAvailable();
if (!is_null($this->updatesFlag)) {
return $this->updatesFlag;
}
$this->updatesFlag = $this->series->updatesAvailable() || !file_exists(Config::getDepsLocalPath());
return $this->updatesFlag;
}/*}}}*/
/* FIXME implement rollback */
@@ -50,6 +57,15 @@ class Manager
$msg .= "No updates are available";
return;
}
$lock = new Lock(Config::getDepsLocalPath());
if (!$lock->locked()) {
$msg .= "Dependencies was updated by another process.";
echo "Another process is updating same dependency path. I'm just going to wait for it to finish and then exit.", PHP_EOL;
$lock->exclusive(true);
unset($lock);
return;
}
}
$series_data = $this->series->getData();
@@ -86,10 +102,16 @@ class Manager
/* This is fine, it's gonna be on the same drive. */
if (!$this->mv($this->path, $new_path)) {
if (!$force) {
unset($lock);
}
throw new Exception("Unable to rename '{$this->path}' to '$new_path'");
}
} else {
if (!$this->rm($this->path)) {
if (!$force) {
unset($lock);
}
throw new Exception("Unable to remove the current dependency dir at '{$this->path}'");
}
}
@@ -97,6 +119,9 @@ class Manager
$up = dirname($this->path);
if (!file_exists($up)) {
if (!$this->md($up)) {
if (!$force) {
unset($lock);
}
throw new Exception("Unable to create '{$this->path}'");
}
}
@@ -118,6 +143,10 @@ class Manager
} else {
$msg .= "No backup was created.";
}
if (!$force) {
unset($lock);
}
}/*}}}*/
}

View File

@@ -2,11 +2,12 @@
namespace SDK\Build\Dependency;
use SDK\Config;
use SDK\Exception;
use SDK\{Config, Exception, FileOps};
class Package
{
use FileOps;
protected $name;
protected $series;
protected $fetcher;
@@ -44,15 +45,8 @@ class Package
if (!$this->filepath || !file_exists($this->filepath)) {
throw new Exception("Invalid filepath '{$this->filepath}'");
}
$zip = new \ZipArchive;
$ret = $zip->open($this->filepath);
if (true === $ret) {
$zip->extractTo($path);
$zip->close();
} else {
throw new Exception("Failed to unpack, error code '$ret'");
}
$this->unzip($this->filepath, $path);
}/*}}}*/
public function cleanup() : void

View File

@@ -0,0 +1,218 @@
<?php
namespace SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Interfaces\Server;
use SDK\Build\PGO\PHP\CLI;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
abstract class PHP
{
protected $php_root;
protected $php_ext_root;
protected function setupPaths()
{
$this->php_root = $this->getRootDir();
if ($this->isDist()) {
$this->php_ext_root = $this->php_root . DIRECTORY_SEPARATOR . "ext";
if (!file_exists($this->php_ext_root)) {
throw new Exception("Extension dir '{$this->php_ext_root}' doesn't exist.");
}
} else {
$this->php_ext_root = $this->php_root;
}
}
/* TODO Might be improved. */
public function isDist() : bool
{
return !file_exists("Makefile") && file_exists("php.exe");
}
protected function createEnv() : array
{
$env = getenv();
if (!$this->isDist()) {
$deps_root = SDKConfig::getDepsLocalPath();
foreach ($env as $k => $v) {
if (strtoupper($k) == "PATH") {
$env[$k] = "$deps_root" . DIRECTORY_SEPARATOR . "bin;" . $env[$k];
break;
}
}
}
return $env;
}
public function getExtRootDir() : string
{
return $this->php_ext_root;
}
public function getRootDir() : string
{
if ($this->php_root) {
return $this->php_root;
}
/* XXX adapt for any possible PHP variants. */
$root = getenv("PHP_SDK_PGO_TEST_PHP_ROOT");
if (!$root) {
if (!$this->isDist()) {
$s = file_get_contents("Makefile");
if (preg_match(",BUILD_DIR=(.+),", $s, $m) > 0) {
$root = trim($m[1]);
}
}
}
if (!file_exists($root)) {
throw new Exception("'$root' doesn't exist.");
}
return $root;
}
public function getVersion(bool $short = false) : string
{
$ret = NULL;
$cli = new CLI($this->conf, $this->scenario);
$out = shell_exec($cli->getExeFilename() . " -n -v");
if ($short) {
if (preg_match(",PHP (\d+\.\d+),", $out, $m)) {
$ret = $m[1];
}
} else {
if (preg_match(",PHP ([^ ]+),", $out, $m)) {
$ret = $m[1];
}
}
if (is_null($ret)) {
throw new Exception("Failed to determine the test PHP version.");
}
return $ret;
}
public function isThreadSafe() : bool
{
$cli = new CLI($this->conf, $this->scenario);
$out = shell_exec($cli->getExeFilename() . " -n -v");
if (preg_match(",NTS,", $out, $m) > 0) {
return false;
}
return true;
}
public function is64bit() : bool
{
$cli = new CLI($this->conf, $this->scenario);
$out = shell_exec($cli->getExeFilename() . " -n -v");
if (preg_match(",x64,", $out, $m) > 0) {
return true;
}
return false;
}
/* Need to cleanup it somewhere. */
public function getIniFilename()
{
$ret = tempnam(sys_get_temp_dir(), "ini");
$tpl_vars = array(
$this->conf->buildTplVarName("php", "extension_dir") => $this->php_ext_root,
$this->conf->buildTplVarName("php", "error_log") => $this->getRootDir() . DIRECTORY_SEPARATOR . "pgo_run_error.log",
);
$k = $this->is64bit() ? "x64" : "x86";
$scenario_vars = (array)$this->conf->getSectionItem("php", "scenario", $this->scenario, "ini", $k);
if ($scenario_vars) {
foreach ($scenario_vars as $k => $v) {
//$tpl_vars[$this->conf->buildTplVarName("php", "scenario", $this->scenario, str_replace(array(".", "-"), "_", $k))] = $v;
$tpl_vars[$this->conf->buildTplVarName("php", str_replace(array(".", "-"), "_", $k))] = $v;
}
}
$this->conf->processTplFile(
$this->getIniTplFilename(),
$ret,
$tpl_vars
);
return $ret;
}
protected function getIniTplFilename()
{
$tpl_path = $this->conf->getTplDir("php");
$version = $this->getVersion(true);
$ts = $this->isThreadSafe() ? "ts" : "nts";
$construct = $tpl_path . DIRECTORY_SEPARATOR . "php-$version-pgo-$ts" . ("default" == $this->scenario ? "" : "-{$this->scenario}") . ".ini";
if (!file_exists($construct)) {
throw new Exception("Couldn't locate PHP config under '$construct'.");
}
return $construct;
}
public function exec(string $php_cmd, string $args = NULL, array $extra_env = array()) : int
{
$env = $this->createEnv();
$exe = $this->getExeFilename();
$ini = $this->getIniFilename();
$cert_path = getenv("PHP_SDK_ROOT_PATH") . "\\msys2\\usr\\ssl\\cert.pem";
$ini .= " -d curl.cainfo=$cert_path";
$spent_key = array();
foreach ($env as $k0 => &$v0) {
foreach ($extra_env as $k1 => $v1) {
if (strtoupper($k0) == strtoupper($k1)) {
/* XXX some more things could require extra handling. */
if (strtoupper($k0) == "PATH") {
$v0 = "$v1;$v0";
} else {
$v0 = $v1;
}
$spent_key[] = $k1;
break;
}
}
}
foreach ($extra_env as $k => $v) {
if (in_array($k, $spent_key)) {
continue;
}
$env[$k] = $v;
}
$cmd = "$exe -n -c $ini " . ($args ? "$args " : "") . "$php_cmd";
$desc = array(
0 => array("file", "php://stdin", "r"),
1 => array("file", "php://stdout", "w"),
2 => array("file", "php://stderr", "w")
);
$p = proc_open($cmd, $desc, $pipes, $this->getRootDir(), $env);
return proc_close($p);
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Interfaces;
class Server
{
public function getName() : string
{
return $this->name;
}
public function getPhp() : Interfaces\PHP
{
return $this->php;
}
}

View File

@@ -0,0 +1,151 @@
<?php
namespace SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool;
class TrainingCase
{
use FileOps;
const TYPE_WEB = "web";
const TYPE_CLI = "cli";
protected $stat = array();
public function getType() : string
{
$type = $this->conf->getSectionItem($this->getName(), "type");
if (!$type) {
$type = "web";
}
return $type;
}
public function run() : void
{
$training = new Tool\Training($this->conf, $this);
$pgo = new Tool\PGO($this->conf, $this->php);
echo "Running " . $this->getName() . " training.\n";
$max_runs = $this->max_runs ?? 1;
$max_runs = (int)$max_runs > 0 ? $max_runs : 1;
$training->run($max_runs, $stat);
if ($this->getType() == "web") {
echo "HTTP responses:\n";
foreach ($stat["http_code"] as $code => $num) {
printf(" %d received %d times\n", $code, $num);
}
if (count($stat["not_ok"]) > 0) {
foreach($stat["not_ok"] as $st) {
echo "Code: $st[http_code], URL: $st[url]", ($st["redirect_url"] ? ", Redirected to: $st[redirect_url]" : ""), "\n";
}
printf("\033[31m WARNING: Not all HTTP responses have indicated success, the PGO data might be unsuitable!\033[0m\n");
}
}
echo $this->getName() . " training complete.\n";
echo "Dumping PGO data for " . $this->getName() . ".\n";
$pgo->dump();
echo "Finished dumping training data for " . $this->getName() . ".\n";
}
public function getHttpPort() : string
{
$port = $this->conf->getSectionItem($this->getName(), "http_port");
if (!$port) {
$port = $this->conf->getNextPort();
$this->conf->setSectionItem($this->getName(), "http_port", $port);
}
return $port;
}
public function getHttpHost() : string
{
$host = $this->conf->getSectionItem($this->getName(), "http_host");
if (!$host) {
$srv = $this->conf->getSrv(
$this->conf->getSectionItem($this->getName(), "srv_http")
);
if ($srv) {
$host = $this->conf->getSectionItem($srv->getName(), "host");
$this->conf->setSectionItem($this->getName(), "http_host", $host);
}
}
return $host;
}
protected function getDbConf(string $item) : string
{
$val = $this->conf->getSectionItem($this->getName(), "db_$item");
if (!$val) {
$srv = $this->conf->getSrv(
$this->conf->getSectionItem($this->getName(), "srv_db")
);
if ($srv) {
$val = $this->conf->getSectionItem($srv->getName(), $item);
$this->conf->setSectionItem($this->getName(), "db_$item", $val);
}
}
return $val;
}
public function getDbPass() : string
{
return $this->getDbConf("pass");
}
public function getDbUser() : string
{
return $this->getDbConf("user");
}
public function getDbHost() : string
{
return $this->getDbConf("host");
}
public function getDbPort() : string
{
return $this->getDbConf("port");
}
public function httpStatusOk(int $status) : bool
{
$ok = array();
$ok = array_merge($ok, range(200, 206));
$ok = array_merge($ok, range(300, 307));
return in_array($status, $ok);
}
public function probeUrl(string $url) : bool
{
$ret = false;
$c = curl_init($url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_exec($c);
if (!curl_errno($c)) {
$st = curl_getinfo($c, CURLINFO_HTTP_CODE);
$ret = $this->httpStatusOk((int)$st);
}
curl_close($c);
return $ret;
}
}

View File

@@ -0,0 +1,371 @@
<?php
namespace SDK\Build\PGO;
use SDK\{Config as SDKConfig, Exception};
class Config
{
const MODE_INIT = 0;
const MODE_RUN = 1;
const MODE_REINIT = 2; /* currently unused */
const MODE_CHECK_INIT = 3;
protected $mode;
protected $last_port = 8081;
protected $sections = array();
protected $scenario = "default";
protected $tpl_vars = array();
protected $srv = array();
public function __construct(int $mode = MODE_RUN)
{
if (self::MODE_CHECK_INIT == $mode) {
// XXX The check is simple right now, so this is sufficient.
return;
}
if (!$this->isInitialized()) {
$this->initWorkDir();
}
if (self::MODE_REINIT == $mode) {
$fn = $this->getWorkSectionsFilename();
if (file_exists($fn)) {
unlink($fn);
}
$mode = self::MODE_INIT;
}
$this->mode = $mode;
$base = getenv("PHP_SDK_ROOT_PATH");
if (self::MODE_INIT == $mode) {
foreach (array("nginx", "mariadb", "postgresql", "php") as $i) {
$this->importSectionFromDir($i, $this->getTplDir() . DIRECTORY_SEPARATOR . $i);
}
} else if (self::MODE_RUN == $mode) {
$fn = $this->getWorkSectionsFilename();
if (!file_exists($fn)) {
throw new Exception("Required config doesn't exist under '$fn'.");
}
$s = file_get_contents($fn);
$this->sections = json_decode($s, true);
foreach($this->sections as $k => $v) {
$this->importTplVars($k, $v);
}
} else {
throw new Exception("Unknown config mode '$mode'.");
}
}
protected function initWorkDir() : void
{
if (!mkdir($this->getWorkDir())) {
throw new Exception("Failed to create " . $this->getWorkDir());
}
}
public function isInitialized()
{
/* XXX Could be some better check. */
return is_dir($this->getWorkDir());
}
public function getToolsDir() : string
{
$base = $this->getWorkDir();
return $base . DIRECTORY_SEPARATOR . "tools";
}
public function getWorkDir() : string
{
$base = getenv("PHP_SDK_ROOT_PATH");
return $base . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "work";
}
public function getPkgCacheDir() : string
{
$base = $this->getWorkDir();
return $base . DIRECTORY_SEPARATOR . "package_cache";
}
public function getJobDir(string $name = NULL) : string
{
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "job";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function getSrvDir(string $name = NULL) : string
{
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "server";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function getHtdocs(string $name = NULL) : string
{
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "htdocs";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function getTplDir(string $name = NULL) : string
{
$ret = getenv("PHP_SDK_ROOT_PATH") . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "tpl";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function getCaseWorkDir(string $name = NULL) : string
{
$ret = $this->getWorkDir() . DIRECTORY_SEPARATOR . "htdocs";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function getCasesTplDir(string $name = NULL) : string
{
$ret = getenv("PHP_SDK_ROOT_PATH") . DIRECTORY_SEPARATOR . "pgo" . DIRECTORY_SEPARATOR . "cases";
if ($name) {
$ret .= DIRECTORY_SEPARATOR . $name;
}
return $ret;
}
public function sectionItemExists(...$args) : bool
{
$i = 0;
$k = strtolower($args[$i]);
$it = $this->sections;
while (array_key_exists($k, $it)) {
$it = $it[$k];
if (++$i >= count($args)) break;
$k = strtolower($args[$i]);
}
return $i == count($args);
}
public function getSectionItem(...$args)
{
$i = 0;
$k = strtolower($args[$i]);
$it = $this->sections;
while (array_key_exists($k, $it)) {
$it = $it[$k];
if (++$i >= count($args)) break;
$k = strtolower($args[$i]);
}
if ($i != count($args)) {
return NULL;
}
return $it;
}
public function setSectionItem(...$args) : void
{
$val = array_pop($args);
$i = 0;
$k = strtolower($args[$i]);
$it = &$this->sections;
while (true) {
$it = &$it[$k];
if (++$i >= count($args)) break;
$k = strtolower($args[$i]);
}
$it = $val;
$this->syncTplVars();
$this->dump();
}
public function importSectionFromDir(string $name, string $dir) : void
{
$fn = $dir . DIRECTORY_SEPARATOR . "phpsdk_pgo.json";
if (!file_exists($fn)) {
throw new Exception("Couldn't import section, file '$fn' doesn't exist.");
}
$s = file_get_contents($fn);
$this->setSectionItem($name, json_decode($s, true));
}
protected function syncTplVars() : void
{
$this->tpl_vars = array();
foreach ($this->sections as $k => $v) {
$this->importTplVars($k, $v);
}
}
public function buildTplVarName(...$args) : string
{
$tpl_k = array("PHP_SDK_PGO");
foreach ($args as $a) {
$tpl_k[] = strtoupper($a);
}
return implode("_", $tpl_k);
}
protected function importTplVars(string $section_name, array $section) : void
{
foreach($section as $k0 => $v0) {
if (is_array($v0)) {
if (substr($k0, -4) == ":env") {
/* Don't put env vars as tpl vars for now. */
continue;
}
$this->importTplVars($section_name . "_" . $k0, $v0);
} else {
$tpl_k = $this->buildTplVarName($section_name, $k0);
$this->tpl_vars[$tpl_k] = $v0;
}
}
}
public function processTpl(string $s, array $additional_vars = array()) : string
{
$vars = array_merge($this->tpl_vars, $additional_vars);
$s = str_replace(array_keys($vars), array_values($vars), $s);
return $s;
}
public function processTplFile(string $tpl_fn, string $dst_fn, array $additional_vars = array()) : void
{
if (!file_exists($tpl_fn)) {
throw new Exception("Template file '$fn' doesn't exist.");
}
$s = file_get_contents($tpl_fn);
if (false === $s) {
throw new Exception("Couldn't read '$tpl_fn'.");
}
$s = $this->processTpl($s, $additional_vars);
if (false === file_put_contents($dst_fn, $s)) {
throw new Exception("Failed to write '$dst_fn'.");
}
}
public function getWorkSectionsFilename()
{
return $this->getWorkDir() . DIRECTORY_SEPARATOR . "phpsdk_pgo.json";
}
public function dump(string $fn = NULL) : void
{
$fn = $fn ? $fn : $this->getWorkSectionsFilename();
$s = json_encode($this->sections, JSON_PRETTY_PRINT);
$ret = file_put_contents($fn, $s);
if (false === $ret || strlen($s) !== $ret) {
throw new Exception("Errors with writing to '$fn'.");
}
}
public function setScenario(string $scenario) : void
{
if (!in_array($scenario, array("default", "cache"), true)) {
throw new Exception("Unknown scenario '$scenario'.");
}
$this->scenario = $scenario;
}
public function getScenario() : string
{
return $this->scenario;
}
public function getNextPort() : int
{
return ++$this->last_port;
}
public function setLastPort(int $port) : void
{
$this->last_port = $port;
}
public function getSdkPhpCmd() : string
{
return getenv("PHP_SDK_PHP_CMD");
}
public function addSrv($item) : void
{
$name = strtolower($item->getName());
if (isset($this->srv[$name])) {
throw new Exception("Server '$name' already exists.");
}
/* XXX Additional checks could not harm. */
$this->srv[$name] = $item;
}
public function getSrv(?string $name = NULL)
{
$ret = NULL;
$name = strtolower($name);
if (!$name) {
return NULL;
} else if ("all" == $name) {
return $this->srv;
} else if (isset($this->srv[$name])) {
return $this->srv[$name];
}
return $ret;
}
}

View File

@@ -0,0 +1,256 @@
<?php
namespace SDK\Build\PGO;
use SDK\{Config as SDKConfig, Exception, Lock};
use SDK\Build\PGO\Config as PGOConfig;
use SDK\Build\PGO\Server\{MariaDB, NGINX, PostgreSQL};
use SDK\Build\PGO\PHP;
use SDK\Build\PGO\Tool\{PGO, PackageWorkman};
use SDK\Build\PGO\Interfaces\TrainingCase;
use SDK\Build\PGO\TrainingCaseIterator;
/* TODO add bench action */
class Controller
{
protected $cmd;
protected $scenario;
protected $conf;
public function __construct(string $cmd, ?string $scenario)
{
$this->cmd = $cmd;
if (NULL == $scenario) {
$scenario = "default";
}
$this->scenario = $scenario;
}
protected function vitalizeSrv()
{
$all = $this->conf->getSrv("all");
if (empty($all)) {
$php_fcgi_tcp = new PHP\FCGI($this->conf, true);
$this->conf->addSrv(new NGINX($this->conf, $php_fcgi_tcp));
$this->conf->addSrv(new MariaDB($this->conf));
/* Uncomment to enable PostgreSQL*/
/* $this->conf->addSrv(new PostgreSQL($this->conf));*/
$all = $this->conf->getSrv("all");
}
return $all;
}
protected function setupConfig($cmd)
{
switch ($cmd) {
default:
throw new Exception("Unknown action '{$cmd}'.");
break;
case "check_init":
$cnf = new PGOConfig(PGOConfig::MODE_CHECK_INIT);
break;
case "init":
$cnf = new PGOConfig(PGOConfig::MODE_INIT);
break;
case "train":
case "up":
case "down":
$cnf = new PGOConfig(PGOConfig::MODE_RUN);
}
$cnf->setScenario($this->scenario);
return $cnf;
}
public function handle($force)
{
/*$mode = (int)("init" !== $this->cmd);
$mode = (PGOConfig::MODE_INIT == $mode && $force) ? PGOConfig::MODE_REINIT : $mode;
$this->conf = new PGOConfig("init" !== $this->cmd);
$this->conf->setScenario($this->scenario);*/
$this->conf = $this->setupConfig($this->cmd);
switch ($this->cmd) {
default:
throw new Exception("Unknown action '{$this->cmd}'.");
break;
case "init":
$lk = new Lock("pgo_init");
if (!$lk->locked()) {
echo "Another process runs initialization right now, waiting.", PHP_EOL;
$lk->exclusive(true);
echo "Another process finished running initialization, I quit as well.", PHP_EOL;
return;
}
$this->init($force);
break;
case "train":
$lk = new Lock("pgo_train");
if (!$lk->locked()) {
echo "Another process runs training right now, I have to wait.", PHP_EOL;
$lk->exclusive(true);
echo "Another process finished training, I may continue.", PHP_EOL;
}
$this->train();
break;
case "up":
$this->up();
break;
case "down":
$this->down($force);
break;
case "check_init":
// pass
break;
}
}
protected function initWorkDirs() : void
{
$dirs = array(
$this->conf->getSrvDir(),
$this->conf->getToolsDir(),
$this->conf->getHtdocs(),
$this->conf->getJobDir(),
$this->conf->getPkgCacheDir(),
);
foreach ($dirs as $dir) {
if (!is_dir($dir)) {
if (!mkdir($dir)) {
throw new Exception("Failed to create '$dir'.");
}
}
}
}
protected function prepareStandaloneTools(PackageWorkman $pw, bool $force = false) : void
{
$php = new PHP\CLI($this->conf);
$composer = $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "composer.phar";
if (!file_exists($composer) || $force) {
/* XXX this needs to go into the config, specifically for composer maybe even separate class. */
$url = "https://getcomposer.org/installer";
$tool = $this->conf->getToolsDir() . DIRECTORY_SEPARATOR . "composer-setup.php";
$pw->fetch($url, $tool, $force);
$php->exec("$tool --install-dir=" . $this->conf->getToolsDir());
unlink($tool);
}
}
public function init(bool $force = false)
{
echo "\nInitializing PGO training environment.\n\n";
$this->initWorkDirs();
$pw = new PackageWorkman($this->conf);
$this->prepareStandaloneTools($pw, $force);
$srvs = $this->vitalizeSrv();
foreach ($srvs as $srv) {
$srv->prepareInit($pw, $force);
}
foreach (new TrainingCaseIterator($this->conf) as $handler) {
$handler->prepareInit($pw, $force);
}
foreach ($srvs as $srv) {
$srv->init();
echo "\n";
}
echo "\n";
foreach (new TrainingCaseIterator($this->conf) as $handler) {
$handler->init();
echo "\n";
}
echo "PGO training environment Initialization complete.\n";
}
public function isInitialized()
{
return $this->conf->isinitialized();
}
public function train()
{
if (!$this->isInitialized()) {
throw new Exception("PGO training environment is not initialized.");
}
echo "\nStarting PGO training using scenario '{$this->scenario}'.\n\n";
$this->up();
/* Clean the PGO db files, only needed once.
Imply also, that any data created during init or
startup is wasted. It is done by dumpbing the data
from the current running processes and subsequently
removing the files. */
$php = $this->conf->getSrv("nginx")->getPhp();
$pgo = new PGO($this->conf, $php);
$pgo->waste();
$pgo->clean();
unset($pgo);
foreach (new TrainingCaseIterator($this->conf) as $handler) {
echo "\n";
$handler->run();
}
/* All the PGC files are merged, simply clean them out. */
$pgo = new PGO($this->conf, $php);
$pgo->clean(true, false);
unset($pgo);
$this->down();
echo "PGO training complete.\n";
}
public function up()
{
if (!$this->isInitialized()) {
throw new Exception("PGO training environment is not initialized.");
}
echo "\nStarting up PGO environment.\n\n";
foreach ($this->vitalizeSrv("all") as $srv) {
$srv->up();
echo "\n";
}
sleep(1);
echo "The PGO environment is up.\n";
}
public function down(bool $force = false)
{
if (!$this->isInitialized()) {
throw new Exception("PGO training environment is not initialized.");
}
/* XXX check it was started of course. */
echo "\nShutting down PGO environment.\n\n";
foreach ($this->vitalizeSrv("all") as $srv) {
$srv->down($force);
echo "\n";
}
sleep(1);
echo "The PGO environment has been shut down.\n";
}
}

View File

@@ -0,0 +1,18 @@
<?php
namespace SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\Tool\PackageWorkman;
interface PHP
{
/* Prepare anything necessary to start initialization, like fetch required packages, etc. */
public function prepareInit(PackageWorkman $pw, bool $force = false) : void;
public function init() : void;
public function up() : void;
public function down(bool $force = false) : void;
public function getVersion(bool $short = false) : string;
public function getExeFilename() : string;
}

View File

@@ -0,0 +1,17 @@
<?php
namespace SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\Tool\PackageWorkman;
interface Server
{
/* Prepare anything necessary to start initialization, like fetch required packages, etc. */
public function prepareInit(PackageWorkman $pw, bool $force = false) : void;
public function init() : void;
public function up() : void;
public function down(bool $force = false) : void;
public function getName() : string;
}

View File

@@ -0,0 +1,13 @@
<?php
namespace SDK\Build\PGO\Interfaces\Server;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\Interfaces;
interface DB extends Interfaces\Server
{
public function __construct(Config $conf);
public function query(string $s, string $db = NULL) : void;
}

View File

@@ -0,0 +1,14 @@
<?php
namespace SDK\Build\PGO\Interfaces\Server;
use SDK\Build\PGO\Config;
use SDK\Build\PGO\Interfaces;
interface HTTP extends Interfaces\Server
{
public function __construct(Config $conf, Interfaces\PHP $php);
public function getPhp() : Interfaces\PHP;
public function addServer(string $part_tpl_fn, array $tpl_vars = array());
}

View File

@@ -0,0 +1,28 @@
<?php
namespace SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\Build\PGO\Tool\PackageWorkman;
interface TrainingCase
{
public function __construct(PGOConfig $conf, ?Server $srv_http, ?Server\DB $srv_db);
/* Name of the training case, usually should be same as dirname and namespace. */
public function getName() : string;
/* Prepare anything necessary to start initialization, like fetch required packages, etc. */
public function prepareInit(PackageWorkman $pw, bool $force = false) : void;
/* Initialize the case, run only once on a new checkout. */
public function init() : void;
/* Run training. */
public function run() : void;
/* Get training type, it's like "web", "cli", etc.*/
public function getType() : string;
}

View File

@@ -0,0 +1,56 @@
<?php
namespace SDK\Build\PGO\PHP;
use SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool\PackageWorkman;
class CLI extends Abstracts\PHP implements Interfaces\PHP
{
protected $conf;
public function __construct(PGOConfig $conf)
{
$this->conf = $conf;
$this->scenario = $conf->getScenario();
$this->setupPaths();
}
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
{
/* pass */
}
public function init() : void
{
/* pass */
}
public function up() : void
{
/* pass */
}
public function down(bool $force = false) : void
{
/* pass */
}
public function getExeFilename() : string
{
$exe = $this->getRootDir() . DIRECTORY_SEPARATOR . "php.exe";
if (!file_exists($exe)) {
throw new Exception("Path '$exe' doesn't exist.");
}
return $exe;
}
}

View File

@@ -0,0 +1,105 @@
<?php
namespace SDK\Build\PGO\PHP;
use SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool\PackageWorkman;
class FCGI extends Abstracts\PHP implements Interfaces\PHP
{
protected $conf;
protected $is_tcp;
public function __construct(PGOConfig $conf, bool $is_tcp)
{
if (!$is_tcp) {
throw new Exception("FCGI training other than through TCP is not implemented yet.");
}
$this->conf = $conf;
$this->is_tcp = $is_tcp;
$this->scenario = $conf->getScenario();
$this->setupPaths();
}
public function getExeFilename() : string
{
$exe = $this->getRootDir() . DIRECTORY_SEPARATOR . "php-cgi.exe";
if (!file_exists($exe)) {
throw new Exception("Path '$exe' doesn't exist.");
}
return $exe;
}
protected function createEnv() : array
{
$env = parent::createEnv();
$fcgi_env = (array)$this->conf->getSectionItem("php", "fcgi:env");
foreach ($fcgi_env as $k => $v) {
$env[$k] = $v;
}
return $env;
}
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
{
}
public function init() : void
{
/* echo "Initializing PHP FCGI.\n";
echo "PHP FCGI initialization done.\n";*/
}
public function up() : void
{
echo "Starting PHP FCGI.\n";
$exe = $this->getExeFilename();
$ini = $this->getIniFilename();
$host = $this->conf->getSectionItem("php", "fcgi", "host");
$port = $this->conf->getSectionItem("php", "fcgi", "port");
$cmd = "start /b $exe -n -c $ini -b $host:$port 2>&1";
$desc = array(
0 => array("file", "php://stdin", "r"),
1 => array("file", "php://stdout", "w"),
2 => array("file", "php://stderr", "w"),
);
$p = proc_open($cmd, $desc, $pipes, $this->getRootDir(), $this->createEnv());
/* Give some time, it might be slow on PGI enabled proc. */
sleep(3);
$c = proc_close($p);
if ($c) {
throw new Exception("PHP FCGI process exited with code '$c'.");
}
/* XXX for Opcache, setup also file cache. */
echo "PHP FCGI started.\n";
}
public function down(bool $force = false) : void
{
echo "Stopping PHP FCGI.\n";
exec("taskkill /f /im php-cgi.exe >nul 2>&1");
echo "PHP FCGI stopped.\n";
}
}

View File

@@ -0,0 +1,123 @@
<?php
namespace SDK\Build\PGO\Server;
use SDK\Build\PGO\Interfaces\Server\DB;
use SDK\Build\PGO\Abstracts\Server;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool\PackageWorkman;
class MariaDB extends Server implements DB
{
use FileOps;
protected $conf;
protected $base;
protected $name = "MariaDB";
public function __construct(PGOConfig $conf)
{
$this->conf = $conf;
$this->base = $conf->getSrvDir(strtolower($this->name));
}
protected function setupDist()
{
/* pass */
}
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
{
$url = $this->conf->getSectionItem($this->name, "pkg_url");
$pw->fetchAndUnzip($url, "mariadb.zip", $this->conf->getSrvDir(), "mariadb", $force);
}
public function init() : void
{
echo "Initializing " . $this->name . ".\n";
$this->setupDist();
$this->up();
$this->down(true);
echo $this->name . " initialization done.\n";
}
public function up() : void
{
echo "Starting " . $this->name . ".\n";
$cwd = getcwd();
chdir($this->base);
$port = $this->conf->getSectionItem($this->name, "port");
//$h = popen("start /b .\\bin\\mysqld.exe --port=$port >nul 2>&1", "r");
$h = popen("start /b .\\bin\\mysqld.exe --port=$port 2>&1", "r");
if (!is_resource($h)) {
chdir($cwd);
throw new Exception("Failed to start MariaDB.");
}
sleep(3);
while (!feof($h)) {
echo fread($h, 1024);
}
pclose($h);
chdir($cwd);
echo $this->name . " started.\n";
}
public function down(bool $force = false) : void
{
echo "Stopping " . $this->name . ".\n";
$cwd = getcwd();
chdir($this->base);
$user = $this->conf->getSectionItem($this->name, "user");
$pass = $this->conf->getSectionItem($this->name, "pass");
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$cmd = sprintf(".\\bin\\mysqladmin.exe --host=$host --port=$port -u $user %s--shutdown_timeout=0 shutdown", ($pass ? "-p$pass " : ""));
exec($cmd);
if ($force) {
sleep(1);
exec("taskkill /f /im mysqld.exe >nul 2>&1");
}
chdir($cwd);
echo $this->name . " stopped.\n";
}
public function query(string $s, string $db = NULL) : void
{
$ret = NULL;
$cwd = getcwd();
chdir($this->base);
$user = $this->conf->getSectionItem($this->name, "user");
$pass = $this->conf->getSectionItem($this->name, "pass");
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$pass_arg = $pass ? "-p$pass " : "";
$ret = shell_exec(".\\bin\\mysql.exe -u $user $pass_arg -h $host -P $port -e \"$s\"");
//var_dump($this->base, getcwd(), ".\\bin\\mysql.exe -u $user $pass_arg -h $host -P $port -e \"$s\"");
chdir($cwd);
}
}

View File

@@ -0,0 +1,151 @@
<?php
namespace SDK\Build\PGO\Server;
use SDK\Build\PGO\Interfaces;
use SDK\Build\PGO\Abstracts;
use SDK\Build\PGO\{Config as PGOConfig};
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool\PackageWorkman;
class NGINX extends Abstracts\Server implements Interfaces\Server\HTTP
{
use FileOps;
protected $name = "NGINX";
protected $conf;
protected $base;
protected $php;
public function __construct(PGOConfig $conf, Interfaces\PHP $php)
{
$this->conf = $conf;
$this->base = $conf->getSrvDir(strtolower($this->name));
$this->php = $php;
}
protected function setupDist() : void
{
$nginx_conf_in = $this->conf->getTplDir($this->name) . DIRECTORY_SEPARATOR . "nginx.conf";
$conf_fn = $this->base . DIRECTORY_SEPARATOR . "conf" . DIRECTORY_SEPARATOR . "nginx.conf";
$vars = array();
$port = $this->conf->getSectionItem($this->name, "port");
if (!$port) {
$port = $this->conf->getNextPort();
$this->conf->setSectionItem($this->name, "port", $port);
}
$vars = array(
$this->conf->buildTplVarName($this->name, "docroot") => str_replace("\\", "/", $this->base . DIRECTORY_SEPARATOR . "html"),
);
$this->conf->processTplFile(
$nginx_conf_in,
$conf_fn,
$vars
);
}
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
{
$url = $this->conf->getSectionItem($this->name, "pkg_url");
$pw->fetchAndUnzip($url, "nginx.zip", $this->conf->getSrvDir(), "nginx", $force);
}
public function init() : void
{
echo "Initializing " . $this->name . ".\n";
$this->setupDist();
$this->upMe();
$this->downMe(true);
echo $this->name . " initialization done.\n";
}
protected function upMe() : void
{
echo "Starting " . $this->name . ".\n";
$cwd = getcwd();
chdir($this->base);
$h = popen("start /b .\\nginx.exe 2>&1", "r");
if (!is_resource($h)) {
chdir($cwd);
throw new Exception("Failed to start MariaDB.");
}
sleep(3);
/* while (!feof($h)) {
echo fread($h, 1024);
}*/
pclose($h);
chdir($cwd);
echo $this->name . " started.\n";
}
public function up() : void
{
$this->php->up();
$this->upMe();
}
public function downMe(bool $force = false) : void
{
echo "Stopping " . $this->name . ".\n";
$cwd = getcwd();
chdir($this->base);
exec(".\\nginx.exe -s quit");
if ($force) {
sleep(1);
exec("taskkill /f /im nginx.exe >nul 2>&1");
}
chdir($cwd);
echo $this->name . " stopped.\n";
}
public function down(bool $force = false) : void
{
$this->php->down();
$this->downMe($force);
}
/* Use only for init phase! */
public function addServer(string $part_tpl_fn, array $tpl_vars = array())
{
if (!file_exists($part_tpl_fn)) {
throw new Exception("Template file '$part_tpl_fn' doesn't exist.");
}
/* We've already did a fresh (re)config, so use the work file now. */
$nginx_conf_in = $this->base . DIRECTORY_SEPARATOR . "conf" . DIRECTORY_SEPARATOR . "nginx.conf";
$cur_conf = file_get_contents($nginx_conf_in);
$in = file_get_contents($part_tpl_fn);
$out = $this->conf->processTpl($in, $tpl_vars);
$tpl = " # PHP_SDK_PGO_NGINX_SERVERS_INC_TPL";
$new_conf = str_replace($tpl, "$out\n$tpl", $cur_conf);
$conf_fn = $this->base . DIRECTORY_SEPARATOR . "conf" . DIRECTORY_SEPARATOR . "nginx.conf";
if (!file_put_contents($conf_fn, $new_conf)) {
throw new Exception("Couldn't write '$conf_fn'.");
}
}
}

View File

@@ -0,0 +1,144 @@
<?php
namespace SDK\Build\PGO\Server;
use SDK\Build\PGO\Interfaces\Server\DB;
use SDK\Build\PGO\Abstracts\Server;
use SDK\Build\PGO\Config as PGOConfig;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Tool\PackageWorkman;
class PostgreSQL extends Server implements DB
{
use FileOps;
protected $conf;
protected $base;
protected $data_dir;
protected $name = "PostgreSQL";
public function __construct(PGOConfig $conf)
{
$this->conf = $conf;
$this->base = $conf->getSrvDir(strtolower($this->name));
$this->data_dir = $this->base . DIRECTORY_SEPARATOR . "data";
}
protected function setupDist()
{
$user = $this->conf->getSectionItem($this->name, "user");
if (!$user) {
$user = trim(shell_exec("pwgen -1 -s 8"));
$this->conf->setSectionItem($this->getName(), "user", $user);
}
$pass = $this->conf->getSectionItem($this->name, "pass");
if (!$pass) {
$pass = trim(shell_exec("pwgen -1 -s 8"));
$this->conf->setSectionItem($this->getName(), "pass", $pass);
}
if (!is_dir($this->data_dir)) {
$pwfile = tempnam(sys_get_temp_dir(), "tmp");
if (strlen($pass) !== file_put_contents($pwfile, $pass)) {
throw new Exception("Couldn't write '$pwfile'.");
}
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "initdb.exe --auth=trust --nosync --username=$user --pwfile=$pwfile --encoding=UTF8 " . $this->data_dir;
//$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "initdb.exe --auth=trust --nosync --username=$user --encoding=UTF8 " . $this->data_dir;
/*echo "$cmd\n";
echo file_get_contents($pwfile) . "\n";*/
exec($cmd);
unlink($pwfile);
}
}
public function prepareInit(PackageWorkman $pw, bool $force = false) : void
{
$url = $this->conf->getSectionItem($this->name, "pkg_url");
$pw->fetchAndUnzip($url, "postgresql.zip", $this->conf->getSrvDir(), "postgresql", $force);
}
public function init() : void
{
echo "Initializing " . $this->name . ".\n";
$this->setupDist();
$this->up();
$this->down(true);
echo $this->name . " initialization done.\n";
}
public function up() : void
{
echo "Starting " . $this->name . ".\n";
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "pg_ctl.exe start -D " . $this->data_dir . " -o \"-h $host -p $port\"";
$h = popen($cmd, "r");
/* XXX error check*/
pclose($h);
echo $this->name . " started.\n";
}
public function down(bool $force = false) : void
{
echo "Stopping " . $this->name . ".\n";
$user = $this->conf->getSectionItem($this->name, "user");
$pass = $this->conf->getSectionItem($this->name, "pass");
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "pg_ctl.exe stop -D " . $this->data_dir . " -m fast";
exec($cmd);
if ($force) {
//sleep(1);
//exec("taskkill /f /im nginx.exe >nul 2>&1");
}
echo $this->name . " stopped.\n";
}
public function createDb(string $db_name) : void
{
$user = $this->conf->getSectionItem($this->name, "user");
$pass = $this->conf->getSectionItem($this->name, "pass");
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "createdb.exe -h $host -p $port -U $user $db_name";
exec($cmd);
}
public function dropDb(string $db_name) : void
{
$user = $this->conf->getSectionItem($this->name, "user");
//$pass = $this->conf->getSectionItem($this->name, "pass");
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "dropdb.exe --if-exists -h $host -p $port -U $user $db_name";
exec($cmd);
}
public function query(string $s, string $db = NULL) : void
{
$ret = NULL;
$user = $this->conf->getSectionItem($this->name, "user");
//$pass = $this->conf->getSectionItem($this->name, "pass");
$host = $this->conf->getSectionItem($this->name, "host");
$port = $this->conf->getSectionItem($this->name, "port");
$db_arg = $db ? "-d $db" : "";
$cmd = $this->base . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "psql.exe -h $host -p $port -U $user $db_arg -c \"$s\"";
$ret = shell_exec($cmd);
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace SDK\Build\PGO\Tool;
use SDK\{Config as SDKConfig, Exception};
use SDK\Build\PGO\Config as PGOConfig;
use SDK\Build\PGO\Interfaces;
class PGO
{
protected $php;
protected $conf;
protected $idx = 0;
public function __construct(PGOConfig $conf, Interfaces\PHP $php)
{
$this->conf = $conf;
$this->php = $php;
}
protected function getPgcName(string $fname) : string
{
$bn = basename($fname, substr($fname, -4, 4));
$dn = dirname($fname);
return $dn . DIRECTORY_SEPARATOR . $bn . "!" . $this->idx . ".pgc";
}
protected function getPgdName(string $fname) : string
{
$bn = basename($fname, substr($fname, -4, 4));
$dn = dirname($fname);
return $dn . DIRECTORY_SEPARATOR . $bn . ".pgd";
}
protected function getWorkItems() : array
{
$exe = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.exe");
$dll = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.dll");
$dll = array_merge($dll, glob($this->php->getExtRootDir() . DIRECTORY_SEPARATOR . "php*.dll"));
/* find out next index */
$tpl = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "php7{ts,}.dll", GLOB_BRACE)[0];
if (!$tpl) {
throw new Exception("Couldn't find php7[ts].dll in the PHP root dir.");
}
do {
if (!file_exists($this->getPgcName($tpl))) {
break;
}
$this->idx++;
} while (true);
return array_unique(array_merge($exe, $dll));
}
public function dump(bool $merge = true) : void
{
$its = $this->getWorkItems();
foreach ($its as $base) {
$pgc = $this->getPgcName($base);
$pgd = $this->getPgdName($base);
`pgosweep $base $pgc`;
//passthru("pgosweep $base $pgc");
if ($merge) {
`pgomgr /merge:1000 $pgc $pgd`;
//passthru("pgomgr /merge:1000 $pgc $pgd");
/* File is already spent, no need to keep it.
If seeing linker warnings about no pgc
were found for some object - most
likely the object were not included in
any training scenario. */
@unlink($pgc);
}
}
}
public function waste() : void
{
$this->dump(false);
}
public function clean(bool $clean_pgc = true, bool $clean_pgd = true) : void
{
if ($clean_pgc) {
$its = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.pgc");
$its = array_merge($its, glob($this->php->getExtRootDir() . DIRECTORY_SEPARATOR . "*" . DIRECTORY_SEPARATOR . "*.pgc"));
foreach (array_unique($its) as $pgc) {
unlink($pgc);
}
}
if ($clean_pgd) {
$its = glob($this->php->getRootDir() . DIRECTORY_SEPARATOR . "*.pgd");
$its = array_merge($its, glob($this->php->getExtRootDir() . DIRECTORY_SEPARATOR . "*" . DIRECTORY_SEPARATOR . "*.pgd"));
foreach (array_unique($its) as $pgd) {
`pgomgr /clear $pgd`;
//passthru("pgomgr /clear $pgd");
}
}
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace SDK\Build\PGO\Tool;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Config as PGOConfig;
class PackageWorkman
{
use FileOps;
protected $conf;
public function __construct(PGOConfig $conf)
{
$this->conf = $conf;
}
public function fetch(string $url, string $tgt_fn, bool $force = false) : void
{
$cache_fn = $this->conf->getPkgCacheDir() . DIRECTORY_SEPARATOR . basename($tgt_fn);
if ($force || !file_exists($cache_fn)) {
echo "Fetching '$url' into '$tgt_fn'\n";
$this->download($url, $cache_fn);
}
if ($force || !file_exists($tgt_fn)) {
if ($cache_fn != $tgt_fn && !$this->cp($cache_fn, $tgt_fn)) {
throw new Exception("Failed to copy '$cache_fn' to '$tgt_fn'.");
}
}
}
/* Only for zips! */
public function fetchAndUnzip(string $url, string $zip_bn, string $zip_tgt_dn, string $tgt_bn = NULL, bool $force = false) : void
{
$cache_fn = $this->conf->getPkgCacheDir() . DIRECTORY_SEPARATOR . $zip_bn;
if ($force || !file_exists($cache_fn)) {
$this->fetch($url, $cache_fn, $force);
}
$tgt_name = $zip_tgt_dn . ($tgt_bn ? DIRECTORY_SEPARATOR . $tgt_bn : "");
if ($force || $tgt_bn && !file_exists($tgt_name) || !$tgt_bn /* This means unzip always if no rename. */) {
echo "Unpacking '$cache_fn' to '$tgt_name'\n";
try {
$this->unzip($cache_fn, $zip_tgt_dn, $tgt_bn);
} catch (Throwable $e) {
$this->rm($cache_fn);
throw $e;
}
}
}
}

View File

@@ -0,0 +1,121 @@
<?php
namespace SDK\Build\PGO\Tool;
use SDK\{Config as SDKConfig, Exception};
use SDK\Build\PGO\Config as PGOConfig;
use SDK\Build\PGO\Interfaces\{TrainingCase, Server, Server\DB, PHP};
class Training
{
protected $conf;
protected $t_case;
public function __construct(PGOConfig $conf, TrainingCase $t_case)
{
$this->conf = $conf;
$this->t_case = $t_case;
if (!in_array($this->t_case->getType(), array("web", "cli"))) {
throw new Exception("Unknown training type '$type'.");
}
}
public function getCase() : TrainingCase
{
return $this->t_case;
}
public function runWeb(int $max_runs, ?array &$stat = array()) : void
{
$url_list_fn = $this->t_case->getJobFilename();
if (!file_exists($url_list_fn)) {
printf("\033[31m WARNING: Job file '$url_list_fn' not found!\033[0m\n");
}
$a = file($url_list_fn, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$stat = array("http_code" => array(), "not_ok" => array());
for ($k = 0; $k < $max_runs; $k++) {
echo ".";
$ch = array();
$mh = curl_multi_init();
foreach ($a as $i => $u) {
$ch[$i] = curl_init($u);
curl_setopt($ch[$i], CURLOPT_CONNECTTIMEOUT_MS, 500000);
curl_setopt($ch[$i], CURLOPT_TIMEOUT_MS, 500000);
curl_setopt($ch[$i], CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch[$i], CURLOPT_USERAGENT, SDKConfig::getSdkUserAgentName());
/* ??? */
/*curl_setopt($ch[$i], CURLOPT_FOLLOWLOCATION, true);*/
curl_multi_add_handle($mh, $ch[$i]);
}
$active = NULL;
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh, 42.0) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
foreach ($ch as $h) {
curl_multi_remove_handle($mh, $h);
/* Gather some stats */
$info = curl_getinfo($h);
$http_code = $info["http_code"];
if (isset($stat["http_code"][$http_code])) {
$stat["http_code"][$http_code]++;
} else {
$stat["http_code"][$http_code] = 1;
}
if (!$this->t_case->httpStatusOk((int)$http_code)) {
$stat["not_ok"][] = $info;
//echo curl_multi_getcontent($h) ;
}
curl_close($h);
}
curl_multi_close($mh);
}
echo "\n";
}
/* TODO Extend with number runs. */
public function run(int $max_runs = 1, ?array &$stat = array()) : void
{
$type = $this->t_case->getType();
switch ($type)
{
case "web":
$this->runWeb($max_runs, $stat);
break;
case "cli":
default:
throw new Exception("Unknown training type '$type'.");
}
}
}

View File

@@ -0,0 +1,102 @@
<?php
namespace SDK\Build\PGO;
use SDK\{Config as SDKConfig, Exception, FileOps};
use SDK\Build\PGO\Config as PGOConfig;
class TrainingCaseIterator implements \Iterator
{
protected $conf;
protected $items = array();
protected $idx;
protected $el;
public function __construct(PGOConfig $conf)
{
$this->rewind();
$this->conf = $conf;
$items = glob($this->conf->getCasesTplDir() . DIRECTORY_SEPARATOR . "*");
foreach ($items as $it) {
if(!is_dir($it)) {
continue;
}
if (!file_exists($this->getHandlerFilename($it))) {
echo "Test case handler isn't present in '$it'.\n";
continue;
}
if ($this->isInactive($it)) {
echo "The test case in '$it' is marked inactive.\n";
continue;
}
$this->items[] = $it;
}
}
protected function isInactive(string $base) : bool
{
return file_exists($base . DIRECTORY_SEPARATOR . "inactive");
}
protected function getHandlerFilename(string $base) : string
{
return $base . DIRECTORY_SEPARATOR . "TrainingCaseHandler.php";
}
public function current()
{
$base = $this->items[$this->idx];
$ns = basename($base);
/* Don't overwrite generated config. */
$it = $this->conf->getSectionItem($ns);
if (!$it) {
$this->conf->importSectionFromDir($ns, $base);
}
require_once $this->getHandlerFilename($base);
$srv_http = $this->conf->getSrv($this->conf->getSectionItem($ns, "srv_http"));
$srv_db = $this->conf->getSrv($this->conf->getSectionItem($ns, "srv_db"));
$class = "$ns\\TrainingCaseHandler";
$this->el = new $class($this->conf, $srv_http, $srv_db);
return $this->el;
}
public function next()
{
$this->idx++;
}
public function rewind()
{
$this->idx = 0;
}
public function valid()
{
return $this->idx < count($this->items);
}
public function key()
{
if (!is_object($this->el)) {
return NULL;
}
return $this->el->getName();
}
}

View File

@@ -36,6 +36,7 @@ class Cache
return file_exists($this->getCacheablePath($path, $relative));
}/*}}}*/
/* TODO Sometimes a timestamp comparison might make sense. */
public function cachedContentDiffers(string $path, string $content, bool $relative = false) : bool
{/*{{{*/
$p = $this->getCacheablePath($path, $relative);
@@ -54,7 +55,26 @@ class Cache
{/*{{{*/
$p = $this->getCacheablePath($path, $relative);
if (strlen($content) !== file_put_contents($p, $content)) {
$to_write = strlen($content);
$wrote = 0;
$fd = fopen($p, "wb");
flock($fd, LOCK_EX);
do {
$got = fwrite($fd, substr($content, $wrote));
if (false == $got) {
break;
}
$wrote += $got;
} while ($wrote < $to_write);
flock($fd, LOCK_UN);
fclose($fd);
if ($to_write !== $wrote) {
throw new Exception("Couldn't cache '$p'");
}
}/*}}}*/

View File

@@ -10,7 +10,8 @@ class Config
{
/* Config variables. */
protected static $depsHost = 'windows.php.net';
protected static $depsPort = 80;
protected static $depsPort = 443;
protected static $depsUriScheme = "https";
protected static $depsBaseUri = "/downloads/php-sdk/deps";
/* protected static $sdkNugetFeedUrl = "http://127.0.0.1/sdk/nuget"; */
@@ -34,6 +35,11 @@ class Config
return self::$depsPort;
}/*}}}*/
public static function getDepsUriScheme() : string
{/*{{{*/
return self::$depsUriScheme;
}/*}}}*/
public static function getDepsBaseUri() : string
{/*{{{*/
return self::$depsBaseUri;
@@ -41,11 +47,13 @@ class Config
public static function setCurrentArchName(string $arch) : void
{/*{{{*/
$arch = strtolower($arch);
if ("x64" != $arch && "x86" != $arch) {
throw new Exception("Unknown arch keyword, either x86 or x64 is accepted");
}
self::$currentArchName = "x64";
self::$currentArchName = $arch;
} /*}}}*/
public static function getCurrentArchName() : string
@@ -53,19 +61,18 @@ class Config
if (NULL === self::$currentArchName) {
/* XXX this might be not true for other compilers! */
passthru("where cl.exe >nul", $status);
if ($status) {
throw new Exception("Couldn't find cl.exe.");
}
exec("cl.exe /? 2>&1", $a, $status);
if ($status) {
throw new Exception("Couldn't execute cl.exe.");
}
if (preg_match(",x64,", $a[0])) {
exec("cl.exe /? 2>&1", $out);
if (preg_match(",x64,", $out[0])) {
self::setCurrentArchName("x64");
} else {
} elseif (preg_match(",x86,", $out[0])) {
self::setCurrentArchName("x86");
} else {
throw new Exception("Couldn't determine Arch.");
}
}
@@ -124,7 +131,7 @@ class Config
if (empty(self::$knownBranches)) {
$cache_file = "known_branches.txt";
$cache = new Cache(self::getDepsLocalPath());
$fetcher = new Fetcher(self::$depsHost, self::$depsPort);
$fetcher = new Fetcher(self::$depsHost, self::$depsPort, self::$depsUriScheme);
$tmp = $fetcher->getByUri(self::$depsBaseUri . "/series/");
if (false !== $tmp) {
@@ -167,26 +174,51 @@ class Config
self::$currentBranchName = $name;
}/*}}}*/
public static function getCurrentBranchName() : ?string
public static function guessCurrentBranchName() : ?string
{/*{{{*/
$branch = NULL;
$found = false;
/* Try to figure out the branch. The worky scenarios are
- CWD is in php-src
- phpize is on the path
FIXME for the dev package, there should be a php-config utility
*/
$fl = "main/php_version.h";
$found = file_exists($fl);
if (!$found) {
exec("where phpize", $out, $status);
if (!$status) {
$fl = dirname($out[0]) . DIRECTORY_SEPARATOR . "include" . DIRECTORY_SEPARATOR . $fl;
$found = file_exists($fl);
}
}
if ($found) {
$s = file_get_contents($fl);
$major = $minor = NULL;
if (preg_match(",PHP_MAJOR_VERSION (\d+),", $s, $m)) {
$major = $m[1];
}
if (preg_match(",PHP_MINOR_VERSION (\d+),", $s, $m)) {
$minor = $m[1];
}
if (is_numeric($major) && is_numeric($minor)) {
$branch = "$major.$minor";
}
}
return $branch;
}/*}}}*/
public static function getCurrentBranchName() : string
{/*{{{*/
if (NULL == self::$currentBranchName) {
/* Try to figure out the branch. For now it only works if CWD is in php-src. */
$fl = "main/php_version.h";
if (file_exists($fl)) {
$s = file_get_contents($fl);
$major = $minor = NULL;
if (preg_match(",PHP_MAJOR_VERSION (\d+),", $s, $m)) {
$major = $m[1];
}
if (preg_match(",PHP_MINOR_VERSION (\d+),", $s, $m)) {
$minor = $m[1];
}
if (is_numeric($major) && is_numeric($minor)) {
self::setCurrentBranchName("$major.$minor");
}
}
$branch = self::guessCurrentBranchName();
self::setCurrentBranchName($branch);
}
return self::$currentBranchName;
@@ -221,7 +253,8 @@ class Config
$data = $branches[$current_branch_name][$cur_crt];
} else {
/* Evaluate CRTs, to avoid ambiquity. */
list($crt, $data) = each($branches[$current_branch_name]);
$crt = key($branches[$current_branch_name]);
$data = $branches[$current_branch_name][$crt];
if ($crt != $cur_crt) {
throw new Exception("The passed CRT '$cur_crt' doesn't match any availbale for branch '$current_branch_name'");
}
@@ -285,9 +318,33 @@ class Config
public static function getDepsLocalPath() : ?string
{/*{{{*/
if (NULL == self::$depsLocalPath) {
if (file_exists("../deps")) {
self::setDepsLocalPath(realpath("../deps"));
} else if (file_exists("main/php_version.h")) {
if (file_exists("Makefile")) {
$s = file_get_contents("Makefile");
if (preg_match(",PHP_BUILD=(.+),", $s, $m)) {
if (isset($m[1])) {
self::setDepsLocalPath(trim($m[1]));
}
}
}
}
if (NULL == self::$depsLocalPath) {
$tmp = dirname(getcwd()) . DIRECTORY_SEPARATOR . "deps";
if (is_dir($tmp)) {
self::setDepsLocalPath($tmp);
}
}
if (NULL == self::$depsLocalPath) {
$tmp = realpath("../deps");
if (is_dir($tmp)) {
self::setDepsLocalPath($tmp);
}
}
if (NULL == self::$depsLocalPath) {
if (file_exists("main/php_version.h")) {
/* Deps dir might not exist. */
self::setDepsLocalPath(realpath("..") . DIRECTORY_SEPARATOR . "deps");
}
@@ -326,6 +383,11 @@ class Config
return $path;
}/*}}}*/
public static function getSdkUserAgentName() : string
{/*{{{*/
return "PHP-SDK-BINARY-TOOLS/" . self::getSdkVersion();
}/*}}}*/
}
/*

View File

@@ -1,163 +1,224 @@
<?php
namespace SDK;
use SDK\Config;
use SDK\Exception;
trait FileOps
{
protected function md(string $name = "", bool $tmp = false) : string
{/*{{{*/
$ret = $name;
if (!$name) {
if ($tmp) {
$pre = Config::getTmpDir();
$ret = $pre . DIRECTORY_SEPARATOR . md5(uniqid());
} else {
throw new Exception("Dir name is empty");
}
}
if (!is_dir($ret)) {
if (!mkdir($ret, 0755, true)) {
throw new Exception("Unable to create '$ret'");
}
}
return $ret;
}/*}}}*/
/* TODO is link and more checks. */
protected function rm(string $path) : bool
{/*{{{*/
if (!file_exists($path)) {
return false;
} else if (is_file($path)) {
return unlink($path);
}
$ret = true;
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator(
$path,
\FilesystemIterator::SKIP_DOTS
),
\RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($iterator as $item) {
if ($item->isDir()) {
$ret = $ret && rmdir($item->getPathname());
} else {
$ret = $ret && unlink($item->getPathname());
}
}
return $ret && rmdir($path);
}/*}}}*/
/* TODO islink and more checks */
protected function cp_or_mv(string $src, string $dst, callable $cb) : bool
{/*{{{*/
if (!file_exists($src)) {
return false;
} else if (is_file($src)) {
return call_user_func($cb, $src, $dst);
}
if (!file_exists($dst)) {
$this->md($dst);
}
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator(
$src,
\FilesystemIterator::SKIP_DOTS
),
\RecursiveIteratorIterator::CHILD_FIRST
);
$cut_len = strlen($src)+1;
foreach ($iterator as $item) {
$src_path = $item->getPathname();
$sub = substr($src_path, $cut_len);
$dst_path = $dst . DIRECTORY_SEPARATOR . $sub;
$dst_parent = dirname($dst_path);
if (!is_dir($dst_parent)) {
if (!$this->md($dst_parent)) {
throw new Exception("Unable to create '$dst_parent'");
}
}
if ($item->isFile()) {
if (!call_user_func($cb, $src_path, $dst_path)) {
throw new Exception("Unable to $cb '$src_path' to '$dst_path'");
}
}
}
return true;
}/*}}}*/
protected function cp(string $src, string $dst) : bool
{/*{{{*/
return $this->cp_or_mv($src, $dst, "copy");
}/*}}}*/
protected function mv(string $src, string $dst) : bool
{/*{{{*/
$ret = $this->cp_or_mv($src, $dst, "rename");
$ret = $ret && $this->rm($src);
return $ret;
}/*}}}*/
protected function download(string $url, string $dest = NULL) : ?string
{
$fd = NULL;
$ch = curl_init($url);
if ($dest) {
$fd = fopen($dest, "w+");
curl_setopt($ch, CURLOPT_FILE, $fd);
} else {
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
}
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$ret = curl_exec($ch);
if (false === $ret) {
$err = curl_error();
curl_close($ch);
if ($dest) {
fclose($fd);
}
throw new Exception($err);
}
curl_close($ch);
if ($dest) {
fclose($fd);
return NULL;
}
return $ret;
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/
<?php
namespace SDK;
use SDK\Config;
use SDK\Exception;
trait FileOps
{
protected function md(string $name = "", bool $tmp = false) : string
{/*{{{*/
$ret = $name;
if (!$name) {
if ($tmp) {
$pre = Config::getTmpDir();
$ret = $pre . DIRECTORY_SEPARATOR . md5(uniqid());
} else {
throw new Exception("Dir name is empty");
}
}
if (!is_dir($ret)) {
if (!mkdir($ret, 0755, true)) {
throw new Exception("Unable to create '$ret'");
}
}
return $ret;
}/*}}}*/
/* TODO is link and more checks. */
protected function rm(string $path) : bool
{/*{{{*/
if (!file_exists($path)) {
return false;
} else if (is_file($path)) {
return unlink($path);
}
$ret = true;
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator(
$path,
\FilesystemIterator::SKIP_DOTS
),
\RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($iterator as $item) {
if ($item->isDir()) {
$ret = $ret && rmdir($item->getPathname());
} else {
$ret = $ret && unlink($item->getPathname());
}
}
return $ret && rmdir($path);
}/*}}}*/
/* TODO islink and more checks */
protected function cp_or_mv(string $src, string $dst, callable $cb) : bool
{/*{{{*/
if (!file_exists($src)) {
return false;
} else if (is_file($src)) {
return call_user_func($cb, $src, $dst);
}
if (!file_exists($dst)) {
$this->md($dst);
}
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator(
$src,
\FilesystemIterator::SKIP_DOTS
),
\RecursiveIteratorIterator::CHILD_FIRST
);
$cut_len = strlen($src)+1;
foreach ($iterator as $item) {
$src_path = $item->getPathname();
$sub = substr($src_path, $cut_len);
$dst_path = $dst . DIRECTORY_SEPARATOR . $sub;
$dst_parent = dirname($dst_path);
if (!is_dir($dst_parent)) {
if (!$this->md($dst_parent)) {
throw new Exception("Unable to create '$dst_parent'");
}
}
if ($item->isFile()) {
if (!call_user_func($cb, $src_path, $dst_path)) {
throw new Exception("Unable to $cb '$src_path' to '$dst_path'");
}
}
}
return true;
}/*}}}*/
protected function cp(string $src, string $dst) : bool
{/*{{{*/
return $this->cp_or_mv($src, $dst, "copy");
}/*}}}*/
protected function mv(string $src, string $dst) : bool
{/*{{{*/
$ret = $this->cp_or_mv($src, $dst, "rename");
$ret = $ret && $this->rm($src);
return $ret;
}/*}}}*/
protected function download(string $url, string $dest_fn = NULL) : ?string
{/*{{{*/
$fd = NULL;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
if ($dest_fn) {
$fd = fopen($dest_fn, "w+");
curl_setopt($ch, CURLOPT_FILE, $fd);
} else {
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
}
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT, Config::getSdkUserAgentName());
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$ret = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (false === $ret || 200 !== $code) {
$err = curl_error($ch);
curl_close($ch);
if ($dest_fn) {
fclose($fd);
}
throw new Exception($err);
}
curl_close($ch);
if ($dest_fn) {
fclose($fd);
return NULL;
}
return $ret;
}/*}}}*/
/* TODO More detailed zip errors. */
protected function unzip(string $zip_fn, string $dest_fn, string $dest_dn = NULL) : void
{/*{{{*/
$zip = new \ZipArchive;
$res = $zip->open($zip_fn);
if (true !== $res) {
throw new Exception("Failed to open '$zip_fn'.");
}
$res = $zip->extractTo($dest_fn);
if (true !== $res) {
$zip->close();
throw new Exception("Failed to unzip '$zip_fn'.");
}
/* Not robust, useful for zips containing one dir sibling only in the root. */
if ($dest_dn) {
$stat = $zip->statIndex(0);
if (false === $stat) {
$zip->close();
throw new Exception("Failed to stat first index in '$zip_fn'.");
}
$zip->close();
/* Index of zero might be not the zipped folder, unusual but true. */
/*$name = $stat["name"];
if ("/" != substr($name, -1)) {
throw new Exception("'$name' is not a directory.");
}
$name = substr($name, 0, -1);*/
$name = rtrim($stat["name"], "/");
while (strchr($name, '/') !== false) {
$name = dirname($name);
}
$old_dir = $dest_fn . DIRECTORY_SEPARATOR . $name;
$new_dir = $dest_fn . DIRECTORY_SEPARATOR . $dest_dn;
if (file_exists($new_dir)) {
if (!$this->rm($new_dir)) {
throw new Exception("Failed to remove '$new_dir'.");
}
}
/* if (!$this->mv($old_dir, $new_dir)) { */
if (!rename($old_dir, $new_dir)) {
throw new Exception("Failed to rename '$old_dir' to '$new_dir'.");
}
} else {
$zip->close();
}
}/*}}}*/
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/

107
lib/php/libsdk/SDK/Lock.php Normal file
View File

@@ -0,0 +1,107 @@
<?php
namespace SDK;
use SDK\{Config, Exception};
class Lock
{
protected $fd;
protected $fn;
protected $locked = false;
protected $wouldBlock = false;
protected $shared = false;
public function __construct(string $tag, bool $auto = true, bool $autoShared = false)
{/*{{{*/
$hash = hash("sha256", $tag);
$this->fn = Config::getTmpDir() . DIRECTORY_SEPARATOR . $hash . ".lock";
if ($auto) {
if ($autoShared) {
$this->shared();
} else {
$this->exclusive();
}
}
}/*}}}*/
public function __destruct()
{/*{{{*/
$this->unlock();
/* We don't really know no one else waits on the same lock yet.*/
/*if (file_exists($this->fn) && !$this->shared) {
@unlink($this->fn);
}*/
}/*}}}*/
public function shared(bool $block = false) : bool
{/*{{{*/
$flags = LOCK_SH;
if (!$block) {
$flags |= LOCK_NB;
}
return $this->doLock($flags);
}/*}}}*/
public function exclusive(bool $block = false) : bool
{/*{{{*/
$flags = LOCK_EX;
if (!$block) {
$flags |= LOCK_NB;
}
return $this->doLock($flags);
}/*}}}*/
protected function doLock(int $flags = LOCK_EX) : bool
{/*{{{*/
if ($this->locked) {
/* Or throw an exception, as we don't know which lock type the outta world expected. */
return true;
}
$this->shared = $flags & LOCK_SH;
if ($this->shared) {
$this->fd = fopen($this->fn, "rb");
} else {
$this->fd = fopen($this->fn, "wb");
}
$this->locked = flock($this->fd, $flags, $this->wouldBlock);
return $this->locked;
}/*}}}*/
public function unlock() : bool
{/*{{{*/
if (!$this->locked) {
return true;
}
$this->doLock(LOCK_UN);
fclose($this->fd);
$this->fd = NULL;
return $this->locked;
}/*}}}*/
public function locked() : bool
{/*{{{*/
return $this->locked;
}/*}}}*/
public function wouldBlock() : bool
{/*{{{*/
return 1 === $this->wouldBlock;
}/*}}}*/
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/

View File

@@ -1,15 +0,0 @@
<?php
function __autoload($name)
{
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . $name . ".php";
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: sw=4 ts=4 fdm=marker
* vim<600: sw=4 ts=4
*/

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More