commit
dc526d354c
|
@ -49,7 +49,6 @@ class ArchivableFilesFinder extends \FilterIterator
|
||||||
$filters = array();
|
$filters = array();
|
||||||
} else {
|
} else {
|
||||||
$filters = array(
|
$filters = array(
|
||||||
new HgExcludeFilter($sources),
|
|
||||||
new GitExcludeFilter($sources),
|
new GitExcludeFilter($sources),
|
||||||
new ComposerExcludeFilter($sources, $excludes),
|
new ComposerExcludeFilter($sources, $excludes),
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
namespace Composer\Package\Archiver;
|
namespace Composer\Package\Archiver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An exclude filter that processes gitignore and gitattributes
|
* An exclude filter that processes gitattributes
|
||||||
*
|
*
|
||||||
* It respects export-ignore git attributes
|
* It respects export-ignore git attributes
|
||||||
*
|
*
|
||||||
|
@ -22,7 +22,7 @@ namespace Composer\Package\Archiver;
|
||||||
class GitExcludeFilter extends BaseExcludeFilter
|
class GitExcludeFilter extends BaseExcludeFilter
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Parses .gitignore and .gitattributes files if they exist
|
* Parses .gitattributes if it exists
|
||||||
*
|
*
|
||||||
* @param string $sourcePath
|
* @param string $sourcePath
|
||||||
*/
|
*/
|
||||||
|
@ -30,12 +30,6 @@ class GitExcludeFilter extends BaseExcludeFilter
|
||||||
{
|
{
|
||||||
parent::__construct($sourcePath);
|
parent::__construct($sourcePath);
|
||||||
|
|
||||||
if (file_exists($sourcePath.'/.gitignore')) {
|
|
||||||
$this->excludePatterns = $this->parseLines(
|
|
||||||
file($sourcePath.'/.gitignore'),
|
|
||||||
array($this, 'parseGitIgnoreLine')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (file_exists($sourcePath.'/.gitattributes')) {
|
if (file_exists($sourcePath.'/.gitattributes')) {
|
||||||
$this->excludePatterns = array_merge(
|
$this->excludePatterns = array_merge(
|
||||||
$this->excludePatterns,
|
$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
|
* Callback parser which finds export-ignore rules in git attribute lines
|
||||||
*
|
*
|
||||||
|
@ -74,6 +56,10 @@ class GitExcludeFilter extends BaseExcludeFilter
|
||||||
return $this->generatePattern($parts[0]);
|
return $this->generatePattern($parts[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count($parts) == 2 && $parts[1] === '-export-ignore') {
|
||||||
|
return $this->generatePattern('!'.$parts[0]);
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,107 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Composer.
|
|
||||||
*
|
|
||||||
* (c) Nils Adermann <naderman@naderman.de>
|
|
||||||
* Jordi Boggiano <j.boggiano@seld.be>
|
|
||||||
*
|
|
||||||
* 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 <naderman@naderman.de>
|
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -156,40 +156,33 @@ class ArchivableFilesFinderTest extends TestCase
|
||||||
{
|
{
|
||||||
$this->skipIfNotExecutable('git');
|
$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(
|
file_put_contents($this->sources.'/.gitattributes', implode("\n", array(
|
||||||
'',
|
'',
|
||||||
'# gitattributes rules with comments and blank lines',
|
'# gitattributes rules with comments and blank lines',
|
||||||
'prefixB.foo export-ignore',
|
'prefixB.foo export-ignore',
|
||||||
//'!/prefixB.foo export-ignore',
|
|
||||||
'/prefixA.foo export-ignore',
|
'/prefixA.foo export-ignore',
|
||||||
'prefixC.* 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());
|
$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()
|
public function testSkipExcludes()
|
||||||
{
|
{
|
||||||
$excludes = array(
|
$excludes = array(
|
||||||
|
|
|
@ -27,14 +27,14 @@ class GitExcludeFilterTest extends TestCase
|
||||||
{
|
{
|
||||||
$filter = new GitExcludeFilter('/');
|
$filter = new GitExcludeFilter('/');
|
||||||
|
|
||||||
$this->assertEquals($expected, $filter->parseGitIgnoreLine($ignore));
|
$this->assertEquals($expected, $filter->parseGitAttributesLine($ignore));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function providePatterns()
|
public function providePatterns()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
array('app/config/parameters.yml', array('{(?=[^\.])app/(?=[^\.])config/(?=[^\.])parameters\.yml(?=$|/)}', false, false)),
|
array('app/config/parameters.yml export-ignore', 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(?=$|/)}', true, false)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Composer.
|
|
||||||
*
|
|
||||||
* (c) Nils Adermann <naderman@naderman.de>
|
|
||||||
* Jordi Boggiano <j.boggiano@seld.be>
|
|
||||||
*
|
|
||||||
* 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)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue