Problem/Motivation
Composer users have to modify autoload.php
to properly use Composer. (Docs: Using Composer in a Drupal project)
Proposed resolution
Leverage wikimedia/composer-merge-plugin to merge the dependencies from core/composer.json
into composer.json
. This allows us to have all dependencies in a single composer file and therefore in a single vendor dir. /vendor
becomes the new vendor directory. We could remove it altogether in a follow-up if d.o infrastructure is ready.
This approach works for core development, contrib modules with composer dependencies and a Sugar-free™ composer development workflow.
Remaining tasks
Undo #2406681: Add an autoload.php in the repo root to control the autoloader of front controllers so that we don't need the top-level autoload.php
file. This is best handled in a follow-up issue.
User interface changes
API changes
Beta phase evaluation
Issue category | Bug, for two reasons. First of all, without this fix, we lose the ability to run composer create-project and composer require which makes composer essentially useless (see http://drupal.org/node/2002304). Second, composer integration is a behavior we are currently trying to support per http://drupal.org/node/2404989, but the only technique available is to modify core. Mod core to use composer is not much of a solution.
Note, however, this is only a bug so long as we are attempting to support composer integration for 8.0 (which I think we should). If we are not attempting to support composer integration for 8.0 then this is not a bug, it is a feature request. |
---|---|
Issue priority | Major |
Prioritized changes | This is a prioritized change because it improves developer experience, allowing Drupal to be used in a way that is more familiar to the greater PHP community. |
Disruption | Essentially none. |
Recommendation | Include in 8.0 |
Comment | File | Size | Author |
---|---|---|---|
#188 | 2380389-188.interdiff.txt | 417 bytes | webflo |
#188 | 2380389-188.patch | 2.13 MB | webflo |
Comments
Comment #1
swentel CreditAttribution: swentel commentedComment #2
davidwbarratt CreditAttribution: davidwbarratt commentedComment #3
davidwbarratt CreditAttribution: davidwbarratt commentedComment #4
davidwbarratt CreditAttribution: davidwbarratt commentedI relized that this issue is not really dependent on #1475510: Remove external dependencies from the core repo and let Composer manage the dependencies instead at all, but #1475510: Remove external dependencies from the core repo and let Composer manage the dependencies instead does resolve this problem (assuming the vendor directory is in the root).
Comment #5
davidwbarratt CreditAttribution: davidwbarratt commentedComment #6
davidwbarratt CreditAttribution: davidwbarratt commentedComment #7
davidwbarratt CreditAttribution: davidwbarratt commentedComment #8
davidwbarratt CreditAttribution: davidwbarratt commentedComment #10
davidwbarratt CreditAttribution: davidwbarratt commentedThat's weird... anyone know why
core/vendor/guzzlehttp/guzzle/tests/perf.php
would have a syntax error when renamed tovendor/guzzlehttp/guzzle/tests/perf.php
?Comment #11
davidwbarratt CreditAttribution: davidwbarratt commentedWould probably help if I fixed all of the references to the vendor directory, not just one. :)
Comment #13
davidwbarratt CreditAttribution: davidwbarratt commentedI forgot that we are excluding vendor directory tests, updating the path of the exclude.
Comment #15
hussainwebThe reason, apparently, is the testbot. The syntax checker might have been configured to skip syntax checks for all files within
core/vendor
. I saw a few other testbot logs (like one here) for patches modifying external libraries and they skip syntax checks for everything withincore/vendor
. Unfortunately, I don't know to whom this should go. Maybe someone at IRC can help.The syntax error is because this particular file needs PHP 5.5. The file in the Drupal core right now needs it too but since they normally skip syntax checks, this did not fail earlier.
Comment #16
neclimdulSome of this work is related to #1475510: Remove external dependencies from the core repo and let Composer manage the dependencies instead
Comment #17
Mile23I can't review the existing patch because it's 1.4mb.
Here's my go. It requires manual testing, using these steps:
composer install
and let it finish../vendor/bin/phpunit -c core/
You have to apply the patch after
composer install
because it re-installs core, obliterating any changes we just made. Also the patch might not apply because we're not sure when the core package was last updated.But you can read the patch and get the idea.
PHPUnit will fail a few tests on the
UnroutedUrlAssemblerTest
test class, because they apparently don't know how to deal with a different core root directory.Hopefully this patch should pass normal testing, because it also allows for the previous behavior of a non-customized vendor directory.
Room for improvement: Create
core/autoload.php
which does this for us in only one place, and change all references tovendor/autoload.php
to load it.Comment #18
Mile23Here's a better version which introduces
core/autoload.php
.It illustrates the concept, but it won't apply after you do
composer install
, but the library is closing so I'll quit here.Comment #20
davidwbarratt CreditAttribution: davidwbarratt commentedMile23,
Well isn't that a clever solution. I was thinking we'd need to have a single
vendor
directory that is outside of /core, but your solution allows for both.Although, it doesn't allow someone to have the vendor directory above the web-root (which is typically where it would be anyways). My solution didn't allow for this either now that I'm thinking about it.
Rather than doing a
file_exists()
on every request, why don't we just have anautoloader_path
as part of the $conf array (or some sort of configuration variable?). That way, if the variable is set, that is what is used, otherwise it defaults to the path inside the core directory.Comment #21
davidwbarratt CreditAttribution: davidwbarratt commentedComment #22
davidwbarratt CreditAttribution: davidwbarratt commentedComment #23
Mile23No, vendor shouldn't be above the web root. It should be alongside whichever composer.json is active. Thus far, it looks like Drupal only lets you have composer.json in one of two places.
Some systems need auto load without the dependencies of the container.
If Drupal weren't wrongheaded about composer, this would be a non-issue. But here we are :-)
Comment #24
davidwbarratt CreditAttribution: davidwbarratt commented#23,
Composer let's you put the vendor directory wherever you want:
https://getcomposer.org/doc/04-schema.md#config
By default, you're correct, it's in
vendor/
of the activecomposer.json
. But there's nothing stopping you from putting in../vendor
for instance.Also, there's nothing stopping you from moving the root
composer.json
file up one level too. In which case the vendor directory would be outside the webroot.I typically follow the Symfony Standard layout which has the
composer.json
andvendor
outside the webroot for increased security:https://github.com/symfony/symfony-standard
Comment #25
davidwbarratt CreditAttribution: davidwbarratt commentedIs there any way to use the
$conf
array that that point?Comment #26
davidwbarratt CreditAttribution: davidwbarratt commentedNevermind, I guess there's not any config that is loaded at that point... I was thinking of what I did in D7:
https://www.drupal.org/project/composer_autoloader
I guess
file_exists()
is probably the way to go, unless we want to move the whole vendor directory up one folder.Comment #27
Mile23We are defining the
composer.json
file, so it's reasonable to assume thatvendor/
will be where we say it is.If someone needs to put
vendor/
somewhere else, they can modifycore/autoload.php
, and by doing so magically change it everywhere.Comment #28
davidwbarratt CreditAttribution: davidwbarratt commented#27,
Makes sense to me. But in that case shouldn't
core/autoload.php
be<root>/autoload.php
? that way it's "user-editable" (i.e. it doesn't get blown away whenever you runcomposer update
)?Comment #29
Mile23OK, here's the same idea, just in /autoload.php.
It should pass the testbot because it works either way. :-)
Manually test it under composer control:
composer install
and let it finish.git apply --reject
in case the patch doesn't apply cleanly.)./vendor/bin/phpunit -c core/
Will need some other way to check out if the simpletest tests work under composer. Probably involving a .travis.yml file.
Comment #31
davidwbarratt CreditAttribution: davidwbarratt commentedThis should be two levels up. :)
Otherwise I think it looks really good.
Comment #32
Mile23Solved the problem with
SimpleTestBrowserTest
, but the problem withSessionHttpsTest
remains becausehttps.php
is devil code.Comment #33
Mile23Hmm. Looks like that fixed itself.
Comment #34
Mile23This is a duplicate: #2406681: Add an autoload.php in the repo root to control the autoloader of front controllers
That issue has patches by a core maintainer, so let's mark this one a dupe.
Comment #35
davidwbarratt CreditAttribution: davidwbarratt commentedI'm reopening this issues, since the goal(s) of this issue were not resolved in #2406681: Add an autoload.php in the repo root to control the autoloader of front controllers
Comment #36
davidwbarratt CreditAttribution: davidwbarratt commentedComment #37
davidwbarratt CreditAttribution: davidwbarratt commentedComment #38
davidwbarratt CreditAttribution: davidwbarratt commentedComment #39
davidwbarratt CreditAttribution: davidwbarratt commented#13 is the most recent patch on this issue.
Comment #40
Mile23Comment #41
Mile23OK, baby steps.
This changes the composer.json file to put its vendor directory in the root directory.
You can apply the small patch and then do this:
This should put all the stuff into vendor/ and all the autoload.php stuff will work.
This patch just deletes the classmap section of the composer.json file. We can re-add this as needed.
Also: Big patch is big.
Comment #42
Mile23Added some desired behaviors to the meta issue here: #2002304: [META] Improve Drupal's use of Composer
This patch supports those goals by making it so no one is required to edit
autoload.php
to point to a differentvendor/
directory.Comment #43
MKorostoff CreditAttribution: MKorostoff commentedComment #44
MKorostoff CreditAttribution: MKorostoff commentedComment #45
MKorostoff CreditAttribution: MKorostoff commentedPatch in #41 not applying on head for me
Comment #46
MKorostoff CreditAttribution: MKorostoff commentedComment #48
Mile23Fixed a problem while making this work: #2445497: Decouple ContainerBuilderTest from Symfony's tests.
Either this one or that one will need a reroll depending on which lands first.
Comment #49
Mile23So just making this patch was a pain, mostly because we keep
vendor/
in the repo. Which is kind of wrong-headed, but there you go.When applied, this patch will introduce whitespace errors, for the same reason.
In order to make the patch, I eventually had to do this:
Anyway, if you can't make the monster patch work for you, there's a smaller patch of just
core/composer.json
andautoload.php
. Apply that, apply the working patch from here: #2445497: Decouple ContainerBuilderTest from Symfony's tests. and then do this:Now you can run unit tests from the root directory, like this:
Comment #51
Mile23#49 fails due to the testbot ignoring the wrong directory: #2460991: Ignore root level vendor/ during testbot lint
Comment #52
Mile23Comment #53
joelpittetThanks for cross linking, didn't know this was already going, I updated your regex-fu slightly on the pifr patch.
Comment #54
bojanz CreditAttribution: bojanz as a volunteer commentedConceptually wouldn't it make more sense to package vendor/ as the vendor directory of drupal/drupal, instead of specifying it as "../vendor" for drupal/core?
Comment #55
Mile23@bojanz: Eventually we'll undo #2406681: Add an autoload.php in the repo root to control the autoloader of front controllers and then it will all just make sense.
But for now, baby steps. :-)
....And now #2460991: Ignore root level vendor/ during testbot lint is in, so yay! We can proceed here.
Comment #56
Mile23We're still waiting on a review of this: #2445497: Decouple ContainerBuilderTest from Symfony's tests.
Patch no longer applies. Special reroll info in #49.
Comment #57
Mile23Comment #58
alexpottAt yesterdays BOF organised by @bojanz we discussed all things composer - through discussion we realised that moving core/vendor outside of core we'd prevent people updating core using a tarball after using composer with a contrib module that needs it. @bojanz is going to explore using https://sculpin.io/documentation/embedded-composer/ to use two vendor directories - one for contrib and one for core. A summary of BOF will be produced sometime soon...
Comment #59
hussainwebI have been thinking long of using embedded composer for this scenario. I think it fits perfectly. @bojanz, please let me know if I can help in any way.
Comment #60
webflo CreditAttribution: webflo commented@alexpott: If a user installed or updated a contrib module with composer already, why is it not feasible to enforce the core update through composer?
Comment #61
alexpott#60 how can we enforce that?
Comment #62
Mile23Restating the problem:
If we have root vendor/, it gets overwritten by the tarball because we're distributing vendor/ with the tarball. That means contrib has to find a way to re-add their requirements.
If we have core/vendor/ it gets overwritten, but that's ok because it's only the vendor directory for core.
If we've used
composer create-project
to create the site, this is not a problem, because core is then a dependency which we can manage withcomposer update
, and in fact modules could declare their dependency on specific core versions.This is a good behavior, but it's also not one that we can rely on since we need to distribute as tarballs.
Comment #63
bojanz CreditAttribution: bojanz as a volunteer commentedI've created #2489646: Start using $root/vendor for non-core dependencies only since it's a completely different approach. Please comment and review.
Comment #64
Crell CreditAttribution: Crell at Palantir.net commentedSomething else that occurred to me sometime after the BoF: Using Composer as a first-class citizen for installing modules is going to force our hand on #1612910: [policy, no patch] Switch to Semantic Versioning for Drupal contrib extensions (modules, themes, etc). If Packagist/Composer is going to be installing modules, then those modules must have a semver-compatible version string. It just won't work otherwise.
I still think we should do it; it's just one more thing we have to factor into our implementation/policy changes.
Comment #65
Mile23Here's a reroll.
Patch introduces whitespace errors because it's moving around non-Drupal code.
If you can't make the big patch apply, try the smaller one and then do:
Note that the changes to
\Drupal\Core\Composer\Composer
illustrate the brittle nature of that kind of premature optimization.Comment #67
Mile23This issue will conflict with #2389243: Remove unnecessary BC-layer in install_drupal() needing a reroll in one or the other.
Comment #68
XanoI'm a little late to the game, so please point me to the appropriate sources if I am missing any important information.
I've been going through the code base, as well as this issue and several others for the past few days, and what I do not understand is why we treat
drupal/core
differently from regular packages:drupal/core
is its own package, so one could argue it should be usable as such. It also has a Composer package type ofdrupal-core
, which makes it special, yet I have not been able to find documentation on how and why this type of package is special.drupal/drupal
is also the package that provides the Composer installer to putdrupal/core
in the correct subdirectory within the application, yet this isn't clear when looking atdrupal/core
itself, for instance if one wants to write a custom front controller.drupal/core
is supposed to be installed within a bigger application. Keeping a separate vendor directory fordrupal/core
undoes Composer's core benefit. This issue is about removing that directory, but why do we keep vendor information in./core/composer.json
and\Drupal\Core\Composer\Composer
?Comment #69
Mile23@xano
#68.1:
So if you look at the root-level
composer.json
file, you'll see that it requirescomposer/installers
.composer/installers
is a composer plugin that knows what a drupal-core package is, and that it should go into the core/ directory. The readme: https://github.com/composer/installers and specifically: https://github.com/composer/installers/blob/7a388b041ee5b6489173b1027e75...So if you do this:
Here's what happens:
Composer sees the root-level composer.json. It looks at the composer.json files of its dependencies (composer/installers and drupal/core). It sees that composer/installers is a plugin and then uses it while installing other packages. composer/installers takes over and puts drupal/core into the core directory.
Basically it overwrites the current core/ directory with the one it just downloaded from d.o.
So now you'd have a versioned core that composer is managing. Unfortunately for us right now, the subtree split isn't completely up to date, so the core you'll then have won't be @dev. The good part is that when/if the subtree split is set up on d.o, you'll be able to update Drupal core by saying
composer update --prefer-stable
.If you want to make a bespoke front controller, having a separate drupal/core package is good news for you. You can now make your own project, and have it depend on drupal/core and not get any of the root-level files. But if you don't also depend on composer/installer, then D8 core will be filed away under /vendor/drupal/core/. This breaks Drupal, so don't do it. (In fact, core should be the one to depend on composer/installers, but let's address that elsewhere.)
#68.2:
Composer also generates class maps for autoloading. The class maps arrays in /core/composer.json and that Composer class are there so common classes don't have to be looked up by the autoloader and are always present in the class map as literals. It's a performance optimization.
Comment #70
Xano@Mile23: thank you for taking the time to explain this so clearly. I was familiar with most of the technical aspects, but it's good you've confirmed what I already thought. My main concern is how all this is documented. There is no README file in
drupal/core
, or documentation in that package's Composer file.I was wondering if those shouldn't also be moved to the application level, but I now realize that would require any front controller package to be bigger than the bare minimum
Comment #71
yched CreditAttribution: yched commentedAlso, note that the template provided in https://github.com/drupal-composer/drupal-project already works pretty good.
Only drawback is that you get duplicated code between (root)/vendor and (root)/web/core/vendor, with the latter being just dead code - that is until we stop committing vendor code in our core repo (aka #1475510: Remove external dependencies from the core repo and let Composer manage the dependencies instead).
Comment #72
timmillwoodA 36MB patch, but moved vendor from"/core" to "/". Also updates it, adds composer.lock to root, removes composer.lock and .gitignore from "/core".
Ideally I'd like to remove the vendor directory, but this seems like a first step.
Comment #74
davidwbarratt CreditAttribution: davidwbarratt commented#72,
If you are renaming/moving things, you can use
git diff -C -M
to make a smaller patch (doesn't work when deleting things though).Comment #75
timmillwoodLet's try this
Comment #77
timmillwoodIf we're using a single vendor directory I think it should go in the /core directory, this patch updates "composer.json" to put vendor in core.
By putting it in core by default it allows those who manage core manually to just copy the latest "core" folder from a zip file to the FTP server. It also allows people to run `composer install` in the root directory and update all the dependencies.
It does however mean most custom dependencies will end up in core, and one using composer you need to continue. This is not such a bad thing, just something that needs to be dictated on a per project basis.
Comment #78
davidwbarratt CreditAttribution: davidwbarratt at Golf Channel commented#77,
I appreciate your enthusiasm, but what you've proposed wont work.
If I update my project's
composer.json
to look like this:and I run
composer update
, Composer will:./core/vendor/league/commonmark
./core
./core
If you see what will happen, league/commonmark will never be installed because it will always be overwritten by drupal/core. The only way around this is to use something like Composer preserve paths to ensure that the path is not overwritten.
If you are a Composer user, you don't manage core manually, you simply execute
composer update
and composer will update everything in./core
for you (as well as resolve all of the dependencies).Comment #79
alexpottThe problem with these statements is that we'll have projects telling people to use composer to install the project - for example Rules and Commerce and then instructions everywhere telling people to download core and copying it over. The once you've used Composer always use Composer is easy to say but it's going to be hard to enforce. This is what discussion in LA concluded and why #2489646: Start using $root/vendor for non-core dependencies only was opened.
Comment #80
timmillwood@alexpott - Thanks for the comments the problem with #2489646: Start using $root/vendor for non-core dependencies only as mentioned in there is it means having to require two autoload.php's, once I updated the autoloader-suffix so it's different in each composer.json I thought I was on to something, but no luck. Also what if core and module X require the same package? will we end up with conflicts?
I am looking to have Drupal 8 is a way (like many other PHP projects) that it can be fully managed via composer, currently that's not an option. I'm happy to go with whatever the consensus as long as it works.
Comment #81
davidwbarratt CreditAttribution: davidwbarratt at Golf Channel commented#80
Why is that not an option?
I'm already doing it here:
https://github.com/davidbarratt/drupal8
Also see this template:
https://github.com/drupal-composer/drupal-project
I've even fully managed Drupal 7 with Composer, so I'm not sure why you think it's not an option.
Comment #82
davidwbarratt CreditAttribution: davidwbarratt at Golf Channel commented#79,
I think this is the more broad ticket #2477789: Use composer to build sites, but yes, I acknowledge that it's a potential issue, and I'm not sure the best way to solve it, but I do know that using a single vendor directory in
./core/vendor
doesn't solve the problem either (nor does reverting #1975220: Allow a Composer user to manage Drupal, modules, and PHP dependencies with a custom root composer.json). :(Comment #83
timmillwood@davidwbarratt - I mainly didn't see it as being possible because I cloned the Drupal git repo, ran `composer update` and I now had two copies of everything, one in /vendor and one in /core/vendor.
Comment #84
yched CreditAttribution: yched commentedSee https://github.com/drupal-composer/drupal-project/issues/23
One drawback of https://github.com/drupal-composer/drupal-project is indeed that you end up with duplicate code between vendor and core/vendor. It's only a cosmetic annoyance, because the project makes sure that the autoloader only ever sees the former (composer managed), and the latter (pulled with drupal/core since it's currently hard-committed in our repo) is only dead code, never actually loaded at runtime. It's just a (very actual) pita when doing searches in your IDE.
But other than that drupal-composer/drupal-project does seem to work fairly well.
Comment #85
davidwbarratt CreditAttribution: davidwbarratt at Golf Channel commented#83,
You're told in the readme exactly what to do:
Basically what you've pointed out is the reason for this issue, it's an annoyance that it's still in
/vendor
, but it works when you update./autoload.php
.Comment #86
timmillwoodTaking a step back I think we need the d.o packager and testbot working with composer before we can move forward.
#1923582: Add ability for testbot to run 'composer install' during installation and #2315545: Install composer dependencies to D8 when packaging run composer install in the core directory, this should therefore work before and after any changes we make.
Comment #87
Mile23One vendor to rule them all: #2554849: phpunit testing crashes if a root vendor directory is used
Comment #88
webflo CreditAttribution: webflo commentedI tried to approach the problem again with the composer-merge-plugin from wikimedia (https://github.com/wikimedia/composer-merge-plugin)
composer-merge-plugin-2380389.patch contains just the changed composer.json the another one moved core/vendor back to vendor.
Comment #89
timmillwoodOn the fence about this issue, but looking forward to discussing it on Tuesday afternoon (if not before!).
Comment #90
webflo CreditAttribution: webflo commentedThe composer-merge-plugin allows us to to a few things.
Comment #93
Mile23Diggit. :-)
So
composer-merge-plugin
is nice and lets me typecomposer install
at the top level and Drupal still works, which means people new to Drupal won't destroy their site by doing what comes naturally.We can still do the subtree split for
create-package
, and if we don't, we can easily pull the twocomposer.json
files together and remove the dependency oncomposer-merge-plugin
.+1.
Just one thing:
That's not true in this patch. The top-level
composer.json
file is a working working. :-)Also, this mechanism of
composer-merge-plugin
could be extended to merge in other arbitrarycomposer.json
files as well, but that's way outside scope here.Comment #94
bojanz CreditAttribution: bojanz as a volunteer commentedI am completely convinced by #88.
It gives us a single vendor directory, and no need to hack autoload.php anymore.
It also resolves the main problem alexpott and others had with the "single vendor" proposal, which is the inability to just replace the core directory if there's been a security update. Meanwhile, nothing's stopping people from modifying composer.json to download core as well if they want to.
I've always felt that blowing away core/ only makes sense if you're starting with Composer (ala Drush Make) in the first place, which is not always the correct assumption.
It allows people to simply do "composer require drupal/commerce" and get the module and its dependencies without any additional steps or dangers.
This finally makes the main part of composer_manager obsolete.
Testing contrib will require a way to point Composer to a local dir for a module, but that should be doable with the new local repository feature Composer has.
Comment #95
davidwbarratt CreditAttribution: davidwbarratt as a volunteer and commentedWell that's a clever solution. I personally would still just add
drupal/core
and use the subtree split, but it seems like it resolves the problems others are having while still allowing people like me to do it more of a "composer way".Only feedback is that perhaps on this:
it should be:
I think that should load the dev version until 1.3.0 is hit, but if I'm wrong feel free to move this back to RTBC.
Comment #96
alexpottI'm a massive +1 to this issue. I think it finally delivers what we want with composer. There are still some tricky things to sort out with respect to managing your project with a mixture of methods - for example starting with composer and then downloading core - but that can be solved with documentation as this is truely an edge case - but this does address my main concerns. Can we file a followup to remove
autoload.php
since this patch makes it obsolete.Also we need a CR and proof that existing sites can work happily with this change. It would also be great to get an issue summary that explains the concerns and how the approach addresses them.
webflo++
Comment #97
davidwbarratt CreditAttribution: davidwbarratt as a volunteer and commentedAlso, you should be able to remove this line since there's no need for Composer Installers if you're not using the subtree split. This should also prevent the dependency from being installed.
You can also remove the readme in
./composer.json
, because there shouldn't be any need to modify./autoload.php
now, but at a minimum, the path in the readme needs to be updated.Comment #98
davidwbarratt CreditAttribution: davidwbarratt as a volunteer commented#96,
I would not remove
./autoload.php
because if we remove it, we are assuming the./vendor
directory is in the docroot, when that is not necessarily the case. I always move it out of the docroot for security reasons, if we remove./autoload.php
I wouldn't be able to do that. :(Comment #99
bojanz CreditAttribution: bojanz as a volunteer commentedWe also need to move the scripts from core/composer.json to composer.json, the merge plugin doesn't merge them and they make sense on the root composer.json anyway.
I've checked the rebased autoload paths (since a merge-plugin issue said it can sometimes be buggy), and they are all rebased correctly.
Untrue. That would prevent you from being able to require modules ("composer require drupal/commerce")
Comment #100
yched CreditAttribution: yched commentedThat approach looks awesome.
Just wondering : https://github.com/wikimedia/composer-merge-plugin/issues/72 seems to hint that the new 'path' repository type added recently in Composer possibly makes composer-merge-plugin moot, so could we solve this with a native 'path' repo ?
Comment #101
bojanz CreditAttribution: bojanz as a volunteer commented@yched
No, we cannot. That allows a local directory to satisfy dependencies, but you still need to specify those dependencies in the first place.
As for:
Feels like a good enough reason to keep it, but we'll need to update the docblock.
Comment #102
davidwbarratt CreditAttribution: davidwbarratt as a volunteer commented#99,
By the same argument, we should add Drupal Packagist to
./composer.json
. Your example only allows you to install packages that are on the standard Packagist.I actually think we should add Drupal Packagist to
./composer.json
, but not everyone agrees. In my mind, we either add Drupal Packagist, put all modules on the standard Packagist, or we remove the dependency on Composer Installers. I just don't see the point in having it if there are only a few modules are on standard Packagist anyways. :/Comment #103
davidwbarratt CreditAttribution: davidwbarratt as a volunteer commented#99,
Also, what happens when Drupal core updates the scripts? Does the user need to manually merge the script list? Doesn't this bring us back to the same problem we had before with the dependencies?
Comment #104
yched CreditAttribution: yched commented@bojanz #101
Right,
- the root composer.json
declares /core as a local 'path' repository,
and requires 'drupal/core'
- /core/composer.json exposes the 'drupal/core' package and lists its 'require's
?
Then if you want to use the subtree split instead, just remove the /core 'path' repo from the root composer.json, and remove /core from your project's git ?
Sorry for the disruption, I'm most probably missing something here, but can't see what atm.
Comment #105
bojanz CreditAttribution: bojanz as a volunteer commentedThere's a parallel discussion going on in #2551607: [meta] Path forward for Composer support about using Drupal Packagist VS Packagist (by automatically creating d.o projects there). Initial consensus was to use Packagist, but if Drupal Packagist wins after all, then it will definitely need to be added. That's out of scope for this issue.
Yes, any additional scripts would need to be manually added.
If we make composer-merge-plugin also merge scripts, then that would resolve your concern and fix the problem before we encounter it.
The current scripts explicitly make sense on the root composer.json and should go there, though.
@yched
It would mean we'd need to keep core/vendor, something we'd want to avoid for confusion sake.
It would also mean we'd need to reinvent merging all of the other keys (such as replace, conflicts, autoload) that composer-merge-plugin handles for us.
Comment #106
webflo CreditAttribution: webflo commentedComment #107
webflo CreditAttribution: webflo commentedComment #108
yched CreditAttribution: yched commentedReally ? I'd expect that, once the drupal/core package is found (locally in that case), its dependencies would get resolved and downloaded to the root /vendor, just like any dependencies of any other packages required by the root composer.json ? So for the tarball we'd just ship core's dependencies in /vendor (i.e. mv core/vendor vendor) ?
Right, indeed. But do those keys make more sense in core/composer.json rather than in the root one ?
I mean, if you use the subtree split by requiring packagist's drupal/core in your root composer.json, those keys from core/composer.json are lost as well, right ?
It seems to me that using a 'path' repo keeps 1:1 consistency between "/core comes from the tarball" or "/core is fetched through the subtree split package" : in both cases it's just the drupal/core package, you just modify where it is fetched from (packagist repo or local 'path' repo), otherwise everything else works the same ? That consistency seems important if we want to support both ?
Comment #109
bojanz CreditAttribution: bojanz as a volunteer commentedOkay, I've just tried to implement "path" as an alternative to the merge plugin.
This is my composer.json:
So basically I kept it all as-is, but also added a pointer to the core directory as one of the repositories.
This didn't work because Composer empties the target directory before download, so core/ was emptied in preparation for core being downloaded, then Composer looked into core/ to find the package... Two conflicting features.
I also tried to remove drupal/core from "require" and add it to "replace" like webflo's patch did, but this resulted in the core dependencies not being downloaded at all.
So, as it stands we still need the composer-merge-plugin.
I think it's a good idea regardless of the problem above, because it also allows you to add a module to modules/ manually (custom module, for example) and then add it to the merge list to still get its composer dependencies. Useful for testing.
Comment #110
Mile23I'd wager it's composer-installer that's emptying the core/ directory.
Anyway, +1 on #109: Don't let the perfect be the enemy of the adequate in this case. We can amend in other issues.
Patch in #88 looking good.
Comment #111
yched CreditAttribution: yched commentedMeanwhile I was testing the 'path' approach myself, and hit the same issue as @bojanz mentions, with Composer's PathDownloader deleting the target dir before trying to symlink to it since it's also the source dir.
That's IMO a bug in the (still recent) 'path' feature : if the local package is already in its final destination (here "/core", as specified by composer-installer for a package of type "drupal-core") then there's nothing to be done to "download" the package, and PathDownloader::download() shouldn't do any deletion or symlinking.
I fixed it with a relatively simple composer patch (will open a PR asap), and things seem to work fine after that.
I still think that the 'path' repo approach is worthwhile, because of :
- native composer support without depending on an additional corpus of code :-)
- the consistency argument at the end of #108 : "use the tarballed /core" and "use the packagist drupal/core subtree split" being just a switch of repository, with the rest of the composer resolution and processing being strictly equal, is IMO very precious if we intend to support both. I'm a bit worried that merging some keys from core/composer.json in one case and not in the other can be very hairpulling in the long run...
However, I agree we shouldn't wait on that being fixed upstream in Composer. If the merge plugin lets us "mv core/vendor vendor" at last, we should probably go for it, and possibly revisit 'path' later ?
Comment #112
yched CreditAttribution: yched commentedYeah, that topic (handling the composer.json of local custom modules) is of high interest to me too, see https://github.com/drupal-composer/drupal-project/issues/25 :-)
But that's a different topic IMO. composer-merge-plugin might very well be the right tool for that case, but I'm not sure it's the right tool for the /core thing, for the reasons in #108 / #111.
Comment #115
yched CreditAttribution: yched commentedPR for the Composer 'path' repo deleting the local folder : https://github.com/composer/composer/pull/4431
Comment #116
bojanz CreditAttribution: bojanz as a volunteer commentedSure, "path" is conceptually cleaner due to there being one magical class less in the process.
On the other hand, supporting local modules (custom development or testing) and a composer_manager-like workflow in general will end up requiring
the merge plugin anyway, bringing us back to the start.
That said, I'm not sure I see the same problem with the merge plugin.
Keep in mind that Composer already merges these keys at runtime.
If drupal/drupal requires drupal/core, then Composer will download drupal/core, parse its composer.json, and merge its requirements, replacements, autoload information, etc. The only thing the merge plugin adds to the process is doing that merge up front for the specified composer.json files. The mechanism is the same.
Comment #117
webflo CreditAttribution: webflo commentedComment #121
Mile23+1 on the concept, shown in
2380389-117-composer.json_.patch
.If only we didn't have to mess around with hairy, delicate patches to
vendor/
. #1475510: Remove external dependencies from the core repo and let Composer manage the dependencies insteadComment #123
webflo CreditAttribution: webflo commentedComment #124
webflo CreditAttribution: webflo commentedComment #127
webflo CreditAttribution: webflo commentedComment #131
webflo CreditAttribution: webflo commentedComment #137
webflo CreditAttribution: webflo commentedComment #140
webflo CreditAttribution: webflo commentedReverted the usage of DRUPAL_ROOT.
Comment #141
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedComment #142
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedFound two other instances of
core/vendor
.Comment #143
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedComment #148
timmillwoodNot sure why it's not failing tests, it should be passing (passes on DrupalCI)
Comment #149
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedDrafted a change record on #2574533.
Comment #150
timmillwoodComment #151
timmillwoodI think issue summary looks good too.
Comment #152
bojanz CreditAttribution: bojanz as a volunteer commentedWe still need to update this comment in autoload.php:
I suggest we just remove it completely.
We also need to move the "scripts" from the core composer.json to the root composer.json
Comment #153
tstoecklerHere's the for-review patch. Generated with the following, after the patch is applied with
--index
in a clean repo:git diff --cached `git status --short | grep -v 'vendor/' | grep -v 'composer.lock' | sed -e 's/M //' -e 's/A //' -e 's/?? //' -e 's/D //'`
X-Post with the above, but the script should work for future patches as well.
Comment #154
hussainwebI am probably missing something. Why do we have this?
Comment #155
hussainwebChanging as per #152. Review patch generated with help of #153. I have not changed anything for #154 yet as I am not clear if that was intentional.
Comment #156
douggreen CreditAttribution: douggreen as a volunteer commentedI tested and confirm that applying the patch does not affect/break existing sites. I created a new D8 site, applied the patch, and then checked that the site was still functional. No cc is necessary.
Comment #157
bojanz CreditAttribution: bojanz as a volunteer commentedWe still haven't moved the scripts :)
Comment #158
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedComment #160
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedComment #165
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedComment #166
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedComment #167
Mile23Quick before it needs a reroll! :-)
What's the difference between #165 and #166?
Comment #168
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedI forgot to add the Plugin in #166
Comment #169
webchickSo! Reviewed this with @webflo tonight at DrupalCon.
Looks like all of the main Composer-y people I know of are on board with this, so that sounds great. The idea of being able to run
composer install
from root again is lovely. And while @alexpott was initially opposed earlier in this issue, looks like he came around in #2380389-96: Use a single vendor directory in the root. He also requested two things; a change record (which is done) and testing on an existing site to make sure it doesn't break.On my local I have Acquia Dev Desktop running PHP 5.5.27 w/ APC cache enabled. I went through the following steps:
drush si
against latest HEADBasically the APCu cache is holding onto the old file paths and isn't notified that the file paths have changed. What we found is one of two things can get you out of this situation:
$settings['rebuild_access'] = TRUE
, then hit /core/rebuild.php, which rebuilds your APCu cache. (No idea how someone is supposed to know how to do that from a PHP fatal error, though. :\)Things that do not work include: going to update.php (same fatal error), deleting the sites/default/files/php directory (no effect, because old files are cached). And, if you revert the patch you have to restart Apache again because now it'll cache the new files. ;)
So we need a few things here:
1) rebuild.php needs to be fixed because it's still pointing to /vendor/autoload.php after this patch (should be /../autoload.php)
2) Also need automated tests of rebuild.php of any kind (separate issue, major?)
3) Make really sure that both the change record and the beta16 release notes call out that this could happen to D8 sites w/ APC and what to do about it.
Needs work for #1.
Comment #170
webchickOh, another thing that doesn't seem to work is
drush cr
. I guess it doesn't clear APCu cache as it goes.Comment #171
webchickIn additional hilarity,
drush cr
could never work, because it's clearing the CLI cache and not the Apache cache. ;) /via @webfloWe tested this with
./php -r "apcu_clear_cache();"
directly.Comment #172
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedI think we can do both in one issue. Created #2575267: Add test coverage for rebuild.php. I am gonna work on it during the extended sprint.
Comment #173
Mile23So what *should* happen is that you solve this by typing
composer install
, and it calls the same code that's used byrebuild.php
to uncachify some stuff, particularly APC. And it should also be called byupdate.php
as a matter of course.So the way forward is:
rebuild.php
into some modular code.rebuild.php
.composer.json
to reset the caches.update.php
as well.How much of that is in scope here? Not enough. There should be another issue and this one should be postponed on it.
Comment #174
hussainwebI just did a round of manual testing as per #169.
$settings['rebuild_access'] = TRUE;
.We should note that reverting the patches and rebuild works because rebuild loads the autoloader within core/vendor. The fix is still required.
Since the fix for rebuild.php is in #2575267: Add test coverage for rebuild.php, should we postpone this on that? Or should we bring in the fix here and deal with the tests in that issue? I have no strong preference because there are pros and cons on each side. If we bring the fix here, we can commit this quicker but doing it there helps us preserve git history.
Comment #175
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedI created #2575495: Invalidate APCu Class Loader automatically if necessary to deal with composers autoload and apcu.
Comment #176
donquixote CreditAttribution: donquixote as a volunteer commentedSee also #2575747: Proposed workflow for Composer + module download on cheap hosting / FTP
Comment #177
Mile23In #2575495: Invalidate APCu Class Loader automatically if necessary #39 there's a way to deal with the issue of ApcClassLoader getting confused when you move the vendor directory (as you might with this patch).
I've folded that in here, because it solves the immediate problem here. There are other concerns it doesn't solve, but those are out of scope in this issue.
See the interdiff for the details.
Using this technique, we overcome the manual test errors in #169, repro'd in #174, so that if you have a Drupal installed with APC, you can just pull the core repro and everything works.
Comment #178
Mile23Ewps. Forgot this.
Also, any clues on how to make a patch that isn't 35 MB would be appreciated. :-)
Comment #179
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedYou have to use
git diff -C -M
.Comment #180
Mile23I think my previous patch broke the testbot, so let's try again with
-C -M
.Comment #181
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedRerolled the patch. The patch is bigger than because i run "composer update --lock" from repo root.
Comment #182
bojanz CreditAttribution: bojanz as a volunteer commentedWe're good to go.
Comment #183
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedPatch in #181 was corrupt.
Comment #184
Mixologic/me wonders why #181 passed... :/
Comment #185
tstoecklerRe #184:
@webflo killed the test run before it finished.
https://www.drupal.org/pift-ci-job/43543 shows that no test results came back, so the "All classes passed!" (which leads to the green color) is theoretically correct, but it really means "No classes passed!" as well. I have no idea where the "14,121 pass" in the summary here came from.
I also saw the actual fatal in the Jenkins output a minute ago, but I can't find it right now. Very strange! In any case that's a DrupalCI issue.
Comment #186
webflo CreditAttribution: webflo at UEBERBIT GmbH commented@Mixologic: #181 >> https://www.drupal.org/pift-ci-job/43543 >> https://dispatcher.drupalci.org/job/default/18834/consoleFull Search for "Drupal\system\Tests\System\HtaccessTest"
Comment #187
webchickK, repeating steps from #169 now that #2575495: Invalidate APCu Class Loader automatically if necessary is in.
drush cr
. Reloaded home page. Same fatal error:Ummmm.... ?
Comment #188
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedInclude path in rebuild.php was wrong.
Comment #189
chx CreditAttribution: chx commentedrebuild.php should put up a message on screen , before it tries anything urging ppl to up the deployment indicator in case it dies. drush should nuke the apcu classloader on cr. Just ideas to avoid a registry like situation.
Comment #190
webchickOk, repeating steps #187...
6. Now instead of a fatal error, it kicks me back to home page with the same fatal error. Not helpful at all, but at least not more fatal errors. :)
8. After manually specifying
$settings['deployment_identifier'] = '8.0.0-beta16';
in settings.php, everything works great. The hypothesis therefore is that none of this monkey-patching will be necessary for "real" users of beta16, since a) they didn't have a deployment_identifier to begin with, so it's obviously going to be different, and b) it'll be on a stable release.Rebuild.php could really use a whole round of "UX" work on it. In addition to what chx says in #189, the variable to turn it on is not even documented in settings.php, and it's confusing as crap that the "r" part of drush cr apparently doesn't invoke the full range of what you'd expect rebuild to do.
Nevertheless, none of that has anything to do with this issue, and the sooner in front of beta16 this is committed, the more time we have to suss out problems. Therefore!
Committed and pushed to 8.0.x. Thanks a LOT, folks!
Comment #191
Mile23We see BAM in #187 and #190 because a) #2575495: Invalidate APCu Class Loader automatically if necessary doesn't actually solve it, and b) my fix in #177 didn't make it into the reroll.
This will continue to affect everyone who pulls the repo until this is fixed.
Apply the interdiff in #177 and try again.
Comment #192
yched CreditAttribution: yched commentedWOOOOHOOOO !!!!
Comment #193
webflo CreditAttribution: webflo at UEBERBIT GmbH commented@Mile23: Please open a follow-up for #191.
Comment #194
Mile23As per IRC chat no need for follow-up. It only really affects devs who can figure out to restart Apache.
But durn I felt really clever for figuring it out. :-)
Comment #198
MKorostoff CreditAttribution: MKorostoff commentedWoohoo! Congrats guys! This is a big win!
Comment #199
jibranHave we created these?
Comment #200
hussainwebCreated #2578033: Remove autoload.php, because the autoloader is always in vendor/autoload.php
Comment #203
claudiu.cristeaUntil this, I used to run a specific phpunit test from core/ directory with:
or all tests:
Now, running the same commands from Drupal root, both are showing only the help text of phpunit.
What's wrong?
Comment #204
claudiu.cristeaIt seems that is working from core/
Maybe related to autoload?
Comment #205
Mile23You have to say
./vendor/bin/phpunit -c core
to pick upphpunit.xml
.Comment #207
webflo CreditAttribution: webflo at UEBERBIT GmbH commentedComment #208
Wim Leers#205: thanks for that, added it to the CR: https://www.drupal.org/node/2574533.
Comment #209
chx CreditAttribution: chx commentedI also updated https://www.drupal.org/node/2012184 to say
Comment #210
yched CreditAttribution: yched commentedSide note : the CR has an unfinished sentence : "core/composer.json gets merged on runtime into the root composer.json with" ;-)
Comment #211
Mile23Just finished that sentence.
Comment #213
Novitsh CreditAttribution: Novitsh at Colruyt Group Services commented@chx I also updated https://www.drupal.org/node/2012184 because it was still assuming that the vendor folder was in core/.