Problem/Motivation
We have discovered, that it is no longer possible to install Drupal 10 on Windows machine when using 10.2.x-dev (11.x branch). It seems like something has changed and the paths to core modules are not resolved correctly, which is causing the InfoParser to complain that core modules does not have core_version_requirement set (which should not be the case). See:
Drupal\Core\Extension\InfoParserException: The 'core_version_requirement' key must be present in D:\htdocs\d10test\core/modules/mysql/mysql.info.yml in Drupal\Core\Extension\InfoParserDynamic->parse() (line 67 of core\lib\Drupal\Core\Extension\InfoParserDynamic.php).
Drupal\Core\Extension\InfoParserDynamic->parse('D:\htdocs\d10test\core/modules/mysql/mysql.info.yml') (Line: 22)
Drupal\Core\Extension\InfoParser->parse('D:\htdocs\d10test\core/modules/mysql/mysql.info.yml') (Line: 210)
Drupal\Core\Extension\DatabaseDriver->getModuleInfo() (Line: 160)
Drupal\Core\Extension\DatabaseDriver->getAutoloadInfo() (Line: 95)
Drupal\Core\Extension\DatabaseDriver->load() (Line: 110)
Drupal\Core\Extension\DatabaseDriver->getInstallTasks() (Line: 110)
Drupal\Core\Extension\DatabaseDriverList->getInstallableList() (Line: 530)
system_requirements('install') (Line: 907)
drupal_check_profile('minimal') (Line: 2084)
install_check_requirements(Array) (Line: 1098)
install_verify_requirements(Array) (Line: 707)
install_run_task(Array, Array) (Line: 578)
install_run_tasks(Array, NULL) (Line: 121)
install_drupal(Object) (Line: 48)
This is only problem on 11.x branch. The last 10.1.x can be installed without problems. I do not think this is related to #3358248: [policy, no patch] Drop support for IIS in Drupal 11.
Steps to reproduce
Try to install 11.x (10.2.x-dev) on windows (xampp or another environment).
Proposed resolution
Find the problem and fix the issue.
Remaining tasks
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #31 | interdiff_29-31.txt | 1.32 KB | poker10 |
| #31 | 3383616-31.patch | 1.2 KB | poker10 |
| #29 | 3383616-29.patch | 2.16 KB | alexpott |
| #29 | 25-29-interdiff.txt | 577 bytes | alexpott |
| #25 | 3383616-25.patch | 1.6 KB | alexpott |
Comments
Comment #2
poker10 commentedI would say this is caused by #3256642: Introduce database driver extensions and autoload database drivers' dependencies, with the introduction of a new
getModuleInfo()function.There is a
DIRECTORY_SEPARATORused, which is\on windows, but in theInfoParserDynamicclass there is still/hardcoded (see/core/):So the path
D:\htdocs\d10test\core/modules/mysql/mysql.info.ymldoes not pass on checkstr_starts_with($filename, $this->root . '/core/').Let's try a patch which simply changes the hardcoded slash for
DIRECTORY_SEPARATOR.Comment #3
poker10 commentedNot sure if we can test this windows-only issue somehow, so will keep this NR for other feedback. Thanks!
Tested the patch also manually and it fixed the error.
Comment #4
poker10 commentedComment #5
shweta__sharma commentedComment #6
smustgrave commentedAnyway to get a test case showing the issue added?
@shweta__sharma can I ask what that tag is meant for?
Thanks!
Comment #7
poker10 commentedI briefly searched the issue queue for Windows issues from the past, but was unable to figure out if/how to provide a failing test for this windows-only issue (if it is possible, any help will be appreciated and feel free to re-set the Needs tests tag again). Therefore also upon the discussion with @smustgrave on Slack, I am moving this back to Needs review.
I am also changing the priority to major, as this bug prevents Drupal 10.2.x from being installed on Windows.
Comment #8
smustgrave commentedThanks for digging @poker10. Going to mark then.
Comment #9
spokjeAs a Windows user, I can confirm the problem and the patch solving the problem.
(In fact I came up independently with the exact same one to get core installing and/or running a test. Just wasn't sure it was something that would be eligible for an official patch on here, since Windows only)
So RTBC+1 from me.
Comment #10
catchPossibly silly question - why doesn't the trailing slash also need to use directory separator?
We've got an issue open to drop support for Windows on production, but even if that gets agreed, issues like this would still be valid fwiw.
Comment #11
poker10 commentedIt seems to be caused by the
ExtensionDiscoveryclass, where paths to extensions are build. This class hasscanDirectory()method, which is building the$pathnamefor eachExtensionobject (this$pathnameis used inInfoParserDynamic::parse()calls subsequently).And the
ExtensionDiscovery::scanDirectory()method is using this code:See also the hardcoded forward slashes in
$absolute_dirand$dir_prefix.Because of that, you will end up with paths like these
D:\htdocs\d10test/core/modules/mysql/mysql.info.ymlfrom the*SplFileInfo*pathName.//edited with the next comment for better explanation :)
Comment #12
poker10 commentedAnd yes, the
ExtensionDiscovery::scanDirectory()is using only this for$pathname:So it will be
core/modules/mysql/mysql.info.yml.But the new
DatabaseDriver::getModuleInfo()is adding$this->rootas well:And
$this->rootis based on\Drupal::root(), which usesdirname(), which returns a path with backslashes on Windows.So:
$this->rootisD:\htdocs\d10testDIRECTORY_SEPARATORis\$this->getModule()->getPathname()iscore/modules/mysql/mysql.info.yml(see the previous comment)So it seems to me that this is causing the paths with backwards and forwards slashes.
Comment #14
spokjeKnow random test RandomTest failure #3376563: Random test fail in Drupal\Tests\Component\Utility\RandomTest::testRandomMachineNamesUniqueness (and yes, I have been waiting weeks to make that crappy joke), back to RTBC.
Comment #16
smustgrave commentedBelieve to be unrelated
Comment #18
spokjeKnown random test failure, back to RTBC.
It would be really nice to get this one in, so I don't have to apply it manually every time I want to install core or run a test locally
Comment #19
spokjeComment #20
alexpottThe mix of hard coded / and DIRECTORY_SEPARATOR feels really icky here. Really hard to explain. Like If we changed it to
str_starts_with($filename, $this->root . DIRECTORY_SEPARATOR . 'core' . DIRECTORY_SEPARATORit would break again on windows.I wonder if instead we should be changing
\Drupal\Core\Extension\DatabaseDriver::getModuleInfo()instead to do:As that would be inline with other calls to \Drupal\Core\Extension\InfoParserDynamic::parse() for extension listing services.
I wonder why $filename is sometimes an absolute path.
I think it'd be good to see if we could somehow make this look a bit better.
Comment #23
xjmI had exactly the same question as #10, and @poker10 explained the reasoning quite well. Adding credit for @catch for posing a helpful question, and @Spokje for jokes. (It's actually for the manual testing, but let's pretend it's the joke.)
Committed to 11.x, and cherry-picked to 10.1.x as a patch-eligible, major-borderline-critical bugfix.
Thanks everyone!
Comment #24
alexpottI think this change might cause more problems though. Because maybe some other custom code that is running on windows as worked around the code as it is Drupal 10.0.x. And now it fails. And the mixture of slashes here is likely to cause more bugs in the future. I think the real issue here is that we should have fixed the new code in
\Drupal\Core\Extension\DatabaseDriver::getModuleInfo()as per #20. I thought I'd set this one to needs work. The only reason we accept a full path in parse() is for testing. Which I might have introduced and now regret.Comment #25
alexpottI think we should revert this from 10.1.x and commit the following patch to 11.x for the quick fix. And then open a follow-up to discuss how we should improve \Drupal\Core\Extension\InfoParserDynamic::parse() so that the paths are more filesystem agnostic.
Comment #26
alexpottAs an example of stuff that would pass on Windows before this change but now will not see
core/tests/Drupal/KernelTests/Config/DefaultConfigTest.phpwhere we do$file_name = DRUPAL_ROOT . '/core/modules/system/tests/themes/' . $name . '/' . $name . '.info.yml';Comment #27
catchIf #25 works that looks fine as a quick fix. Definitely we should try to minimise the mix of slashes, it's very confusing just reading it, let alone trying to figure out what the practical effects might be.
Comment #29
alexpottSo #25 is failing because PHPUnit tests don't set the working directory to Drupal root but extension discovery including now database driver discovery assumes that you are in Drupal root. There are other unit tests that set the working directory for this reason so UrlConversionTest can do the same. I think we might consider throwing an exception in \Drupal\Core\Extension\DatabaseDriver::getModuleInfo() if
$this->infois an empty array as that means an info file does not exist which is not really valid.Comment #30
xjmThis unit test maybe? Otherwise it sounds like a robot's version of first person.
Is #29 intended for both 11.x and 10.1.x? (And wouldn't it have been better to just revert it first anyway?)
Comment #31
poker10 commentedThanks all for your effort with this issue! I have tested the patch #29 and it seems to work on Windows as the patch #2. Given the severity of this (unable to install or update 11.x branch on Windows), I think that it would be good to have one of these quick fixes committed (#2 or this new approach). @alexpott raised some concerns about the patch #2 in #24, so in that case it would probably be safer to commit the later one.
The issue which caused this was committed to 11.x branch only: #3256642: Introduce database driver extensions and autoload database drivers' dependencies , so I think it should be sufficient to commit the fix to the 11.x. And the cleanest way probably will be to revert both commits and commit the patch I am uploading now - it is the same as #29, but without the code being reverted (as it will be reverted separately).
I have also updated this comment in the uploaded patch.
@alexpott Do you mean here, or in the follow-up?
Thanks!
Comment #32
alexpottDefinitely a follow-up.
Yep we can revert #2 from 10.1.x and 11.x and then commit #31. I'll do the reverts and then someone can rtbc this.
Comment #35
smustgrave commentedPer #32
Comment #36
catchCommitted/pushed to 11.x, thanks!
Comment #38
xjmI think this still needs that followup filed?
Comment #39
alexpottCreated #3391776: InfoParser returns an empty array if passed a non-existing file and #3391778: InfoParserDynamic::parse() looks for strings in a file path without normalising as followups.