From 126f95a8d75d81bc8c2701209f957c449aa9e1a6 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Wed, 24 Nov 2021 22:44:03 +0100 Subject: [PATCH] Get rid of gitignore/hgignore handling (fixes #7358), Add support for -export-ignore (fixes #9153) --- .../Archiver/ArchivableFilesFinder.php | 1 - .../Package/Archiver/GitExcludeFilter.php | 26 +---- .../Package/Archiver/HgExcludeFilter.php | 107 ------------------ .../Archiver/ArchivableFilesFinderTest.php | 89 ++++----------- .../Package/Archiver/GitExcludeFilterTest.php | 6 +- .../Package/Archiver/HgExcludeFilterTest.php | 43 ------- 6 files changed, 30 insertions(+), 242 deletions(-) delete mode 100644 src/Composer/Package/Archiver/HgExcludeFilter.php delete mode 100644 tests/Composer/Test/Package/Archiver/HgExcludeFilterTest.php diff --git a/src/Composer/Package/Archiver/ArchivableFilesFinder.php b/src/Composer/Package/Archiver/ArchivableFilesFinder.php index 128043797..7ee4e90ad 100644 --- a/src/Composer/Package/Archiver/ArchivableFilesFinder.php +++ b/src/Composer/Package/Archiver/ArchivableFilesFinder.php @@ -49,7 +49,6 @@ class ArchivableFilesFinder extends \FilterIterator $filters = array(); } else { $filters = array( - new HgExcludeFilter($sources), new GitExcludeFilter($sources), new ComposerExcludeFilter($sources, $excludes), ); diff --git a/src/Composer/Package/Archiver/GitExcludeFilter.php b/src/Composer/Package/Archiver/GitExcludeFilter.php index f08d460f7..896c3946b 100644 --- a/src/Composer/Package/Archiver/GitExcludeFilter.php +++ b/src/Composer/Package/Archiver/GitExcludeFilter.php @@ -13,7 +13,7 @@ namespace Composer\Package\Archiver; /** - * An exclude filter that processes gitignore and gitattributes + * An exclude filter that processes gitattributes * * It respects export-ignore git attributes * @@ -22,7 +22,7 @@ namespace Composer\Package\Archiver; class GitExcludeFilter extends BaseExcludeFilter { /** - * Parses .gitignore and .gitattributes files if they exist + * Parses .gitattributes if it exists * * @param string $sourcePath */ @@ -30,12 +30,6 @@ class GitExcludeFilter extends BaseExcludeFilter { parent::__construct($sourcePath); - if (file_exists($sourcePath.'/.gitignore')) { - $this->excludePatterns = $this->parseLines( - file($sourcePath.'/.gitignore'), - array($this, 'parseGitIgnoreLine') - ); - } if (file_exists($sourcePath.'/.gitattributes')) { $this->excludePatterns = array_merge( $this->excludePatterns, @@ -47,18 +41,6 @@ class GitExcludeFilter extends BaseExcludeFilter } } - /** - * Callback line parser which process gitignore lines - * - * @param string $line A line from .gitignore - * - * @return array{0: string, 1: bool, 2: bool} An exclude pattern for filter() - */ - public function parseGitIgnoreLine($line) - { - return $this->generatePattern($line); - } - /** * Callback parser which finds export-ignore rules in git attribute lines * @@ -74,6 +56,10 @@ class GitExcludeFilter extends BaseExcludeFilter return $this->generatePattern($parts[0]); } + if (count($parts) == 2 && $parts[1] === '-export-ignore') { + return $this->generatePattern('!'.$parts[0]); + } + return null; } } diff --git a/src/Composer/Package/Archiver/HgExcludeFilter.php b/src/Composer/Package/Archiver/HgExcludeFilter.php deleted file mode 100644 index 95880475e..000000000 --- a/src/Composer/Package/Archiver/HgExcludeFilter.php +++ /dev/null @@ -1,107 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Package\Archiver; - -use Symfony\Component\Finder; - -/** - * An exclude filter that processes hgignore files - * - * @author Nils Adermann - */ -class HgExcludeFilter extends BaseExcludeFilter -{ - const HG_IGNORE_REGEX = 1; - const HG_IGNORE_GLOB = 2; - - /** - * Either HG_IGNORE_REGEX or HG_IGNORE_GLOB - * @var int - */ - protected $patternMode; - - /** - * Parses .hgignore file if it exist - * - * @param string $sourcePath - */ - public function __construct($sourcePath) - { - parent::__construct($sourcePath); - - $this->patternMode = self::HG_IGNORE_REGEX; - - if (file_exists($sourcePath.'/.hgignore')) { - $this->excludePatterns = $this->parseLines( - file($sourcePath.'/.hgignore'), - array($this, 'parseHgIgnoreLine') - ); - } - } - - /** - * Callback line parser which process hgignore lines - * - * @param string $line A line from .hgignore - * - * @return array{0: string, 1: bool, 2: bool}|null An exclude pattern for filter() - */ - public function parseHgIgnoreLine($line) - { - if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) { - if ($matches[1] === 'glob') { - $this->patternMode = self::HG_IGNORE_GLOB; - } else { - $this->patternMode = self::HG_IGNORE_REGEX; - } - - return null; - } - - if ($this->patternMode == self::HG_IGNORE_GLOB) { - return $this->patternFromGlob($line); - } - - return $this->patternFromRegex($line); - } - - /** - * Generates an exclude pattern for filter() from a hg glob expression - * - * @param string $line A line from .hgignore in glob mode - * - * @return array{0: string, 1: bool, 2: bool} An exclude pattern for filter() - */ - protected function patternFromGlob($line) - { - $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#'; - $pattern = str_replace('[^/]*', '.*', $pattern); - - return array($pattern, false, true); - } - - /** - * Generates an exclude pattern for filter() from a hg regexp expression - * - * @param string $line A line from .hgignore in regexp mode - * - * @return array{0: string, 1: bool, 2: bool} An exclude pattern for filter() - */ - public function patternFromRegex($line) - { - // WTF need to escape the delimiter safely - $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#'; - - return array($pattern, false, true); - } -} diff --git a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php index 90db564fa..b98e59589 100644 --- a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php +++ b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php @@ -156,40 +156,33 @@ class ArchivableFilesFinderTest extends TestCase { $this->skipIfNotExecutable('git'); - file_put_contents($this->sources.'/.gitignore', implode("\n", array( - '# gitignore rules with comments and blank lines', - '', - 'prefixE.foo', - '# and more', - '# comments', - '', - '!/prefixE.foo', - '/prefixD.foo', - 'prefixF.*', - '!/*/*/prefixF.foo', - '', - 'refixD.foo', - '/C', - 'D/prefixA', - 'E', - 'F/', - 'G/*', - 'H/**', - 'J/', - 'parameters.yml', - '\!important!.txt', - '\#*', - ))); - - // git does not currently support negative git attributes file_put_contents($this->sources.'/.gitattributes', implode("\n", array( '', '# gitattributes rules with comments and blank lines', 'prefixB.foo export-ignore', - //'!/prefixB.foo export-ignore', '/prefixA.foo export-ignore', 'prefixC.* export-ignore', - //'!/*/*/prefixC.foo export-ignore', + '', + 'prefixE.foo export-ignore', + '# and more', + '# comments', + '', + '/prefixE.foo -export-ignore', + '/prefixD.foo export-ignore', + 'prefixF.* export-ignore', + '/*/*/prefixF.foo -export-ignore', + '', + 'refixD.foo export-ignore', + '/C export-ignore', + 'D/prefixA export-ignore', + 'E export-ignore', + 'F/ export-ignore', + 'G/* export-ignore', + 'H/** export-ignore', + 'J/ export-ignore', + 'parameters.yml export-ignore', + '\!important!.txt export-ignore', + '\#* export-ignore', ))); $this->finder = new ArchivableFilesFinder($this->sources, array()); @@ -207,46 +200,6 @@ class ArchivableFilesFinderTest extends TestCase )); } - public function testHgExcludes() - { - $this->skipIfNotExecutable('hg'); - - file_put_contents($this->sources.'/.hgignore', implode("\n", array( - '# hgignore rules with comments, blank lines and syntax changes', - '', - 'pre*A.foo', - 'prefixE.foo', - '# and more', - '# comments', - '', - '^prefixD.foo', - 'D/prefixA', - 'parameters.yml', - '\!important!.txt', - 'E', - 'F/', - 'syntax: glob', - 'prefixF.*', - 'B/*', - 'H/**', - ))); - - $this->finder = new ArchivableFilesFinder($this->sources, array()); - - $expectedFiles = $this->getArchivedFiles( - 'hg init && '. - 'hg add && '. - 'hg commit -m "init" && '. - 'hg archive archive.zip' - ); - - // Remove .hg_archival.txt from the expectedFiles - $archiveKey = array_search('/.hg_archival.txt', $expectedFiles); - array_splice($expectedFiles, $archiveKey, 1); - - $this->assertArchivableFiles($expectedFiles); - } - public function testSkipExcludes() { $excludes = array( diff --git a/tests/Composer/Test/Package/Archiver/GitExcludeFilterTest.php b/tests/Composer/Test/Package/Archiver/GitExcludeFilterTest.php index eae607a9b..e8cae5853 100644 --- a/tests/Composer/Test/Package/Archiver/GitExcludeFilterTest.php +++ b/tests/Composer/Test/Package/Archiver/GitExcludeFilterTest.php @@ -27,14 +27,14 @@ class GitExcludeFilterTest extends TestCase { $filter = new GitExcludeFilter('/'); - $this->assertEquals($expected, $filter->parseGitIgnoreLine($ignore)); + $this->assertEquals($expected, $filter->parseGitAttributesLine($ignore)); } public function providePatterns() { return array( - array('app/config/parameters.yml', array('{(?=[^\.])app/(?=[^\.])config/(?=[^\.])parameters\.yml(?=$|/)}', false, false)), - array('!app/config/parameters.yml', array('{(?=[^\.])app/(?=[^\.])config/(?=[^\.])parameters\.yml(?=$|/)}', true, false)), + array('app/config/parameters.yml export-ignore', array('{(?=[^\.])app/(?=[^\.])config/(?=[^\.])parameters\.yml(?=$|/)}', false, false)), + array('app/config/parameters.yml -export-ignore', array('{(?=[^\.])app/(?=[^\.])config/(?=[^\.])parameters\.yml(?=$|/)}', true, false)), ); } } diff --git a/tests/Composer/Test/Package/Archiver/HgExcludeFilterTest.php b/tests/Composer/Test/Package/Archiver/HgExcludeFilterTest.php deleted file mode 100644 index 21a0260da..000000000 --- a/tests/Composer/Test/Package/Archiver/HgExcludeFilterTest.php +++ /dev/null @@ -1,43 +0,0 @@ - - * Jordi Boggiano - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Composer\Test\Package\Archiver; - -use Composer\Package\Archiver\HgExcludeFilter; -use Composer\Test\TestCase; - -class HgExcludeFilterTest extends TestCase -{ - /** - * @dataProvider providePatterns - * - * @param string $ignore - * @param mixed[] $expected - */ - public function testPatternEscape($ignore, $expected) - { - $filter = new HgExcludeFilter('/'); - - $this->assertEquals($expected, $filter->patternFromRegex($ignore)); - } - - public function providePatterns() - { - return array( - array('.#', array('#.\\##', false, true)), - array('.\\#', array('#.\\\\\\##', false, true)), - array('\\.#', array('#\\.\\##', false, true)), - array('\\\\.\\\\\\\\#', array('#\\\\.\\\\\\\\\\##', false, true)), - array('.\\\\\\\\\\#', array('#.\\\\\\\\\\\\\\##', false, true)), - ); - } -}