1
0
Fork 0

Merge pull request #9465 from BR0kEN-/issues/9464

#9464: ZipArchiver incorrectly treats `.gitignore` directory inclusions
pull/9651/head
Jordi Boggiano 2021-01-26 10:42:26 +01:00 committed by GitHub
commit 471a63c206
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 29 deletions

View File

@ -123,26 +123,25 @@ abstract class BaseExcludeFilter
protected function generatePattern($rule) protected function generatePattern($rule)
{ {
$negate = false; $negate = false;
$pattern = '{'; $pattern = '';
if (strlen($rule) && $rule[0] === '!') { if ($rule !== '' && $rule[0] === '!') {
$negate = true; $negate = true;
$rule = substr($rule, 1); $rule = ltrim($rule, '!');
} }
if (strlen($rule) && $rule[0] === '/') { $firstSlashPosition = strpos($rule, '/');
$pattern .= '^/'; if (0 === $firstSlashPosition) {
$rule = substr($rule, 1); $pattern = '^/';
} elseif (strlen($rule) - 1 === strpos($rule, '/')) { } elseif (false === $firstSlashPosition || strlen($rule) - 1 === $firstSlashPosition) {
$pattern .= '/'; $pattern = '/';
$rule = substr($rule, 0, -1);
} elseif (false === strpos($rule, '/')) {
$pattern .= '/';
} }
$rule = trim($rule, '/');
// remove delimiters as well as caret (^) and dollar sign ($) from the regex // remove delimiters as well as caret (^) and dollar sign ($) from the regex
$pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)'; $rule = substr(Finder\Glob::toRegex($rule), 2, -2);
return array($pattern . '}', $negate, false); return array('{'.$pattern.$rule.'(?=$|/)}', $negate, false);
} }
} }

View File

@ -18,20 +18,44 @@ use Composer\Package\Archiver\ZipArchiver;
class ZipArchiverTest extends ArchiverTest class ZipArchiverTest extends ArchiverTest
{ {
public function testZipArchive() /**
* @param string $include
*
* @dataProvider provideGitignoreExcludeNegationTestCases
*/
public function testGitignoreExcludeNegation($include)
{
$this->testZipArchive(array(
'docs/README.md' => '# The doc',
'.gitignore' => "/*\n.*\n!.git*\n$include",
));
}
public function provideGitignoreExcludeNegationTestCases()
{
return array(
array('!/docs'),
array('!/docs/'),
);
}
public function testZipArchive(array $files = array())
{ {
if (!class_exists('ZipArchive')) { if (!class_exists('ZipArchive')) {
$this->markTestSkipped('Cannot run ZipArchiverTest, missing class "ZipArchive".'); $this->markTestSkipped('Cannot run ZipArchiverTest, missing class "ZipArchive".');
} }
$files = array( if (empty($files)) {
'file.txt', $files = array(
'foo/bar/baz', 'file.txt' => NULL,
'x/baz', 'foo/bar/baz' => NULL,
'x/includeme', 'x/baz' => NULL,
); 'x/includeme' => NULL,
if (!Platform::isWindows()) { );
$files[] = 'foo' . getcwd() . '/file.txt';
if (!Platform::isWindows()) {
$files['foo' . getcwd() . '/file.txt'] = NULL;
}
} }
// Set up repository // Set up repository
$this->setupDummyRepo($files); $this->setupDummyRepo($files);
@ -41,12 +65,12 @@ class ZipArchiverTest extends ArchiverTest
// Test archive // Test archive
$archiver = new ZipArchiver(); $archiver = new ZipArchiver();
$archiver->archive($package->getSourceUrl(), $target, 'zip'); $archiver->archive($package->getSourceUrl(), $target, 'zip');
$this->assertFileExists($target); static::assertFileExists($target);
$zip = new ZipArchive(); $zip = new ZipArchive();
$res = $zip->open($target); $res = $zip->open($target);
self::assertTrue($res, 'Failed asserting that Zip file can be opened'); static::assertTrue($res, 'Failed asserting that Zip file can be opened');
foreach ($files as $file) { foreach ($files as $path => $content) {
$this->assertSame('content', $zip->getFromName($file), 'Failed asserting that Zip contains ' . $file); static::assertSame($content, $zip->getFromName($path), 'Failed asserting that Zip contains ' . $path);
} }
$zip->close(); $zip->close();
@ -57,12 +81,15 @@ class ZipArchiverTest extends ArchiverTest
* Create a local dummy repository to run tests against! * Create a local dummy repository to run tests against!
* @param array $files * @param array $files
*/ */
protected function setupDummyRepo($files) protected function setupDummyRepo(array &$files)
{ {
$currentWorkDir = getcwd(); $currentWorkDir = getcwd();
chdir($this->testDir); chdir($this->testDir);
foreach ($files as $file) { foreach ($files as $path => $content) {
$this->writeFile($file, 'content', $currentWorkDir); if ($files[$path] === NULL) {
$files[$path] = 'content';
}
$this->writeFile($path, $files[$path], $currentWorkDir);
} }
chdir($currentWorkDir); chdir($currentWorkDir);