Open saeideng opened 4 years ago
Interesting issue.
This approach is indeed bound to fail since we use the name
attribute as primary key, so the result is expected.
I'm not sure yet as to what approach would be best though, because I don't yet understand your use case: What's the reason you want two versions of the same package installed concurrently?
I do understand the potential need to install a different version based on the OS or PHP Version - and that currently phive does not yet have an answer to that.
So, what's your use case for multiple concurrent versions?
when you have several application with different requirements you need to have several version of a tool
for example about phpunit
that there are applications that phpunit requirement at them is not same and they are not compatible well with latest version of phpunit yet
I do this manually right now , but I like the phive supports this feature a day thanks for your good tool
Okay, I believe I do understand. We'll have to discuss how to implement something like that.
I do understand the potential need to install a different version based on the OS or PHP Version - and that currently phive does not yet have an answer to that.
Can this be supported eventually? It is very useful tor tools like PHPUnit which only support latest two versions. This means that you will need both PHPUnit 8 and PHPUnit 9 (separately) if you want to support and test PHP 7.2-8.0.
I think that this could be done with supporting more version constraints, like how Composer supportes them. So you could have version="^8.5|^9.2"
to support both PHPUnit versions.
In addition to this, it might also be good to split version
, installed
and copy
keys into different files, similarly to composer.json
and composer.lock
. This is because if you have version="^8.5|^9.2" installed="9.2.6"
in the same file, and then use that file on older PHP version, it could cause problems. If you use Git, you also can't just remove installed
key and commit it because it will reappear on next install and cause messy diffs. It is also similar for copy
, because this is most likely reference of user and not of project. However, location
should stay in main file, because project's build tools may depend on specific location.
If you have two files, main one could be commited to Git and would contain PHAR name, requested/supported version and file location, and PHIVE won't try to edit it unless requested (i.e. by adding or removing new PHAR). Lock file could be ignored by Git (or included if project wants it), would only generate on install and would contain which specific version is currently installed.
Thank you for providing additional input to this.
I still disagree though: Neither you nor the original poster need to install multiple versions of the same phar at the same time, as the issue title and the overall wording in the descriptions suggest. As said before, I don't see a use case for this. What I understood before and find reconfirmed in your addition is that there is a need to have conditional installations. One such condition could be the PHP Version or the OS it's running on.
I also strongly disagree with having a combined constrained. It doesn't specify when to choose which version and, given we do not have any meta data for phars before downloading them, we cannot possibly resolve such a configuration without downloading multiple phars first (e.g. for every fragment of the combined version constraint) and try to figure out which one might actually work.
This is inherently getting worse if we are to support extension installation, which also suffers from not having meta-data available - but that's a different topic (#88).
Last but not least, I don't agree with the reasoning regarding single versus multiple files. Even for composer it is highly recommended to commit both, the composer.json
as well as the composer.lock
file to ensure you get exactly the previously selected versions of your dependencies.
If you always have to commit both files though, separating them is not helping. It only leads to additional complexity - for instance the case that composer complains about that the lock file is out of sync.
Again, what we need is conditional installations. For example, it could look like this:
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit" version="^8.5" installed="8.5.1" location="./tools/phpunit" copy="true" condition="phpunit-8" />
<condition name="phpunit-8">
<php constraint="^7.4" />
<env var="foo" value="bar" />
</condition>
</phive>
The above has not yet been implemented and is just a brain-dump ;)
I do also have this problem for the testing environment of hollodotme/fast-cgi-client where I need 3 different versions of PHPUnit to run tests against all supported PHP versions. But I want to add 3 more cents here:
phars.xml
gets altered when using phive install
(not update
), too.IMO this should not happen at all and is maybe worth a separate issue.
When running phive install
the phars.xml
should be treated as a lock file, like composer.lock
when running composer install
. Only phive update
or the user should be allowed to change the phars.xml
.
Before:
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit" version="7.5.19" installed="7.5.19" location="./.tools/phpunit-7.phar" copy="true"/>
<phar name="phpunit" version="8.5.19" installed="8.5.19" location="./.tools/phpunit-8.phar" copy="true"/>
<phar name="phpunit" version="9.5.8" installed="9.5.8" location="./.tools/phpunit-9.phar" copy="true"/>
<phar name="phpstan" version="^0.12.94" installed="0.12.94" location="./.tools/phpstan.phar" copy="true"/>
<phar name="composer" version="^2.1.5" installed="2.1.5" location="./.tools/composer.phar" copy="true"/>
</phive>
Run phive install: (Works as expected on the first run only)
Phive 0.15.0 - Copyright (C) 2015-2021 by Arne Blankerts, Sebastian Heuer and Contributors
Fetching repository list
Downloading https://phar.phpunit.de/phive.xml
Downloading https://phar.phpunit.de/phpunit-7.5.19.phar
Downloading https://phar.phpunit.de/phpunit-7.5.19.phar.asc
Copying phpunit-7.5.19.phar to /Users/hollodotme/Sites/hollodotme/fast-cgi-client/.tools/phpunit-7.phar
Downloading https://phar.phpunit.de/phpunit-8.5.19.phar
Downloading https://phar.phpunit.de/phpunit-8.5.19.phar.asc
Copying phpunit-8.5.19.phar to /Users/hollodotme/Sites/hollodotme/fast-cgi-client/.tools/phpunit-8.phar
Downloading https://phar.phpunit.de/phpunit-9.5.8.phar
Downloading https://phar.phpunit.de/phpunit-9.5.8.phar.asc
Copying phpunit-9.5.8.phar to /Users/hollodotme/Sites/hollodotme/fast-cgi-client/.tools/phpunit-9.phar
Downloading https://github.com/phpstan/phpstan/releases/download/0.12.94/phpstan.phar
Downloading https://github.com/phpstan/phpstan/releases/download/0.12.94/phpstan.phar.asc
Copying phpstan-0.12.94.phar to /Users/hollodotme/Sites/hollodotme/fast-cgi-client/.tools/phpstan.phar
Downloading https://github.com/composer/composer/releases/download/2.1.5/composer.phar
Downloading https://github.com/composer/composer/releases/download/2.1.5/composer.phar.asc
Copying composer-2.1.5.phar to /Users/hollodotme/Sites/hollodotme/fast-cgi-client/.tools/composer.phar
After phive install
:
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit" version="9.5.8" installed="9.5.8" location="./.tools/phpunit-9.phar" copy="true"/>
<phar name="phpunit" version="8.5.19" installed="8.5.19" location="./.tools/phpunit-8.phar" copy="true"/>
<phar name="phpunit" version="9.5.8" installed="9.5.8" location="./.tools/phpunit-9.phar" copy="true"/>
<phar name="phpstan" version="^0.12.94" installed="0.12.94" location="./.tools/phpstan.phar" copy="true"/>
<phar name="composer" version="^2.1.5" installed="2.1.5" location="./.tools/composer.phar" copy="true"/>
</phive>
My use case is that I install all needed PHARs in one go and use them later in different docker containers, in order to run the test suites against different PHP (and PHPUnit) versions. This happens ins a build matrix on github actions which executes make
tasks for the current PHP version.
I run phive via docker container, too.
So I maintain the conditions what version of a PHAR is used in a specific make
task and don't want to maintain this additionally in the phars.xml
in the form of conditionals as proposed in the comments here. This would lead to (unnecessary) multiple calls of phive install
during the process and adds the complexity of WHY a PHAR must be installed to the phive
configuration.
Configuring the desired PHARs for installing & updating as listed in the phars.xml
above should remain a dead simple list.
As already said, phive install
should not change the phars.xml
and phive update
should update one PHAR after the other according to their version constraints. In my case this would lead to no updates for PHPUnit PHARs at all, because the versions are pinned. Only PHPStan and composer should be updated automatically.
I don't know the internals of phive
or why the name attribute must be unique. If that is a prerequisite, I can also imagine a config structure like this:
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit">
<version required="7.5.19" installed="7.5.19" location="./.tools/phpunit-7.phar" copy="true"/>
<version required="8.5.19" installed="8.5.19" location="./.tools/phpunit-8.phar" copy="true"/>
<version required="9.5.8" installed="9.5.8" location="./.tools/phpunit-9.phar" copy="true" />
</phar>
</phive>
IMO phive
should not know why or when to install a phar (conditions), it should only know which PHARs to install.
I do also have this problem for the testing environment of hollodotme/fast-cgi-client where I need 3 different versions of PHPUnit to run tests against all supported PHP versions. But I want to add 3 more cents here:
1. The
phars.xml
gets altered when usingphive install
(notupdate
), too.
That's not correct - or at least I cannot reproduce that:
theseer@nyda /tmp/x6 main $ cat .phive/phars.xml
<?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit" version="^9.5.8" installed="9.5.8" location="./tools/phpunit" copy="false"/>
</phive>
theseer@nyda /tmp/x6 main $ rm -rf tools
theseer@nyda /tmp/x6 main $ git status
On branch main
nothing to commit, working tree clean
theseer@nyda /tmp/x6 main $ phive install
Phive 0.15.0-7-g17cf2ee - Copyright (C) 2015-2021 by Arne Blankerts, Sebastian Heuer and Contributors
Fetching repository list
Downloading https://phar.phpunit.de/phpunit-9.5.8.phar
Downloading https://phar.phpunit.de/phpunit-9.5.8.phar.asc
Linking /home/theseer/.phive/phars/phpunit-9.5.8.phar to /tmp/x6/tools/phpunit
theseer@nyda /tmp/x6 main $ git status
On branch main
nothing to commit, working tree clean
theseer@nyda /tmp/x6 main $
IMO this should not happen at all and is maybe worth a separate issue.
It doesn't ;) - see above.
When running
phive install
thephars.xml
should be treated as a lock file, likecomposer.lock
when runningcomposer install
. Onlyphive update
or the user should be allowed to change thephars.xml
.
Phive only updates the phars.xml
when a change is made: Either by having a new phar added via explicit install call or when an update is performed.
Before:
<?xml version="1.0" encoding="UTF-8"?> <phive xmlns="https://phar.io/phive"> <phar name="phpunit" version="7.5.19" installed="7.5.19" location="./.tools/phpunit-7.phar" copy="true"/> <phar name="phpunit" version="8.5.19" installed="8.5.19" location="./.tools/phpunit-8.phar" copy="true"/> <phar name="phpunit" version="9.5.8" installed="9.5.8" location="./.tools/phpunit-9.phar" copy="true"/> <phar name="phpstan" version="^0.12.94" installed="0.12.94" location="./.tools/phpstan.phar" copy="true"/> <phar name="composer" version="^2.1.5" installed="2.1.5" location="./.tools/composer.phar" copy="true"/> </phive>
Having multiple entries with the same name is explicitly not supported as - at least currently - this is a primary key. I assume that phive gets confused and tries to update the first entrty for phpunit with whatever happend last as it sees that as a change to be recorded.
2. Maintaining conditions
My use case is that I install all needed PHARs in one go and use them later in different docker containers, in order to run the test suites against different PHP (and PHPUnit) versions. This happens ins a build matrix on github actions which executes
make
tasks for the current PHP version.I run phive via docker container, too.
While I of course do understand the general setup described as well as the need to have different versions of tools installed depending on the PHP-Versions, I don't understand why one would want the added complexity of having differing names for the executables or paths?
IMHO, having a fixed name for the executable and thus identical build targets would make maintaining the build logic a lot easier.
Not sure how github actions do that but when you cache phive's source library (usually ~/.phive), a "local" phive install
using a specific PHP version would make phive pick the appropriate version - assuming we would implement my suggestion above or something comparable to that - without any additional downloads. You can even specify to "prefer offline".
So I maintain the conditions what version of a PHAR is used in a specific
make
task and don't want to maintain this additionally in thephars.xml
in the form of conditionals as proposed in the comments here. This would lead to (unnecessary) multiple calls ofphive install
during the process and adds the complexity of WHY a PHAR must be installed to thephive
configuration.
I do understand that line of thought but I consider it backwards: In your setup, we have a split brain: The phive
configuration has the location and version constraint but which version to actually use is somewhere else. I don't think you do need that "somewhere else" but should have phive
handle all of that and just run the build target as needed.
3. How I would like it to function
Configuring the desired PHARs for installing & updating as listed in the
phars.xml
above should remain a dead simple list.As already said,
phive install
should not change thephars.xml
andphive update
should update one PHAR after the other according to their version constraints.
That's how it's actually implemented.
In my case this would lead to no updates for PHPUnit PHARs at all, because the versions are pinned. Only PHPStan and composer should be updated automatically.
Just to repeat: We do not support having the same phar name appear more than once. Other than that, that's how things are implemented.
I don't know the internals of
phive
or why the name attribute must be unique. If that is a prerequisite, I can also imagine a config structure like this:<?xml version="1.0" encoding="UTF-8"?> <phive xmlns="https://phar.io/phive"> <phar name="phpunit"> <version required="7.5.19" installed="7.5.19" location="./.tools/phpunit-7.phar" copy="true"/> <version required="8.5.19" installed="8.5.19" location="./.tools/phpunit-8.phar" copy="true"/> <version required="9.5.8" installed="9.5.8" location="./.tools/phpunit-9.phar" copy="true" /> </phar> </phive>
IMO
phive
should not know why or when to install a phar (conditions), it should only know which PHARs to install.
I honestly consider your approach an edge case. The default scenario is, as far as I believe at least, to have one build target to run the tests and one would expect the matching version of PHPUnit to be installed depending on the PHP version in use.
With the proposed structure, there is no simple installation via CLI anymore: Assuming you have the above config, what would phive install phpunit@^10.0
do? Add it to the list because somehow that's what you implicitly mean? Replace the list with only ^10.0
? If we'd add it to the list, how do we determine the location name? And, if we have only one version installed, how do we explicitly install a different version? Do we assume, if you only have one version currently, you want it swapped out?
And, worse, when the phar to be installed contains a manifest, we'll perform compatibility checks for it. That would horribly break if we'd attempt your implementation idea.
I'm not sure what the best approach is, but I'm fairly certain, this isn't it ;) So far, among all the potentially sub optimal ideas, the conditionals are imho the best.
my
phive.xml
I run
phive update
resultI want to link second phar file to
bin/phpunit8
notbin/phpunit7
my
phive.xml
after update