diff --git a/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php b/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php index da734613be7a..d9ad2b10543b 100644 --- a/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php @@ -286,58 +286,25 @@ private function buildDatesFiltering(Command $command, array $dates) /** * @param Command $command - * @param array $contains - * @param Boolean $not + * @param string $sort + * + * @throws \InvalidArgumentException */ - private function buildContentFiltering(Command $command, array $contains, $not = false) + private function buildSorting(Command $command, $sort) { - foreach ($contains as $contain) { - $expr = Expression::create($contain); - - // todo: avoid forking process for each $pattern by using multiple -e options - $command - ->add('| xargs -r grep -I') - ->add($expr->isCaseSensitive() ? null : '-i') - ->add($not ? '-L' : '-l') - ->add('-Ee')->arg($expr->renderPattern()); - } + $this->buildFormatSorting($command, $sort); } /** * @param Command $command * @param string $sort - * - * @throws \InvalidArgumentException */ - private function buildSorting(Command $command, $sort) - { - switch ($sort) { - case SortableIterator::SORT_BY_NAME: - $command->ins('sort')->add('| sort'); - - return; - case SortableIterator::SORT_BY_TYPE: - $format = '%y'; - break; - case SortableIterator::SORT_BY_ACCESSED_TIME: - $format = '%A@'; - break; - case SortableIterator::SORT_BY_CHANGED_TIME: - $format = '%C@'; - break; - case SortableIterator::SORT_BY_MODIFIED_TIME: - $format = '%T@'; - break; - default: - throw new \InvalidArgumentException('Unknown sort options: '.$sort.'.'); - } - - $this->buildFormatSorting($command, $format); - } + abstract protected function buildFormatSorting(Command $command, $sort); /** * @param Command $command - * @param string $format + * @param array $contains + * @param Boolean $not */ - abstract protected function buildFormatSorting(Command $command, $format); + abstract protected function buildContentFiltering(Command $command, array $contains, $not = false); } diff --git a/src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php b/src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php index 2114f437b8ae..aeb71dd5518d 100644 --- a/src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php @@ -13,6 +13,8 @@ use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Shell\Command; +use Symfony\Component\Finder\Iterator\SortableIterator; +use Symfony\Component\Finder\Expression\Expression; /** * Shell engine implementation using BSD find command. @@ -34,21 +36,65 @@ public function getName() */ protected function canBeUsed() { - // FIXME: this adapter does not work yet with Shell::TYPE_DARWIN - return in_array($this->shell->getType(), array(Shell::TYPE_BSD)) && parent::canBeUsed(); + return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed(); } /** * {@inheritdoc} */ - protected function buildFormatSorting(Command $command, $format) + protected function buildFormatSorting(Command $command, $sort) { + switch ($sort) { + case SortableIterator::SORT_BY_NAME: + $command->ins('sort')->add('| sort'); + + return; + case SortableIterator::SORT_BY_TYPE: + $format = '%HT'; + break; + case SortableIterator::SORT_BY_ACCESSED_TIME: + $format = '%a'; + break; + case SortableIterator::SORT_BY_CHANGED_TIME: + $format = '%c'; + break; + case SortableIterator::SORT_BY_MODIFIED_TIME: + $format = '%m'; + break; + default: + throw new \InvalidArgumentException('Unknown sort options: '.$sort.'.'); + } + $command - ->get('find') ->add('-print0 | xargs -0 stat -f') - ->arg($format.' %h/%f\\n') - ->add('| sort | cut') - ->arg('-d ') - ->arg('-f2-'); + ->arg($format.'%t%N') + ->add('| sort | cut -f 2'); + } + + /** + * {@inheritdoc} + */ + protected function buildFindCommand(Command $command, $dir) + { + parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1); + return $command; + } + + /** + * {@inheritdoc} + */ + protected function buildContentFiltering(Command $command, array $contains, $not = false) + { + foreach ($contains as $contain) { + $expr = Expression::create($contain); + + // todo: avoid forking process for each $pattern by using multiple -e options + $command + ->add('| grep -v \'^$\'') + ->add('| xargs grep -I') + ->add($expr->isCaseSensitive() ? null : '-i') + ->add($not ? '-L' : '-l') + ->add('-Ee')->arg($expr->renderPattern()); + } } } diff --git a/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php b/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php index 6f5a4eb21269..a235742c01e6 100644 --- a/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php @@ -13,6 +13,8 @@ use Symfony\Component\Finder\Shell\Shell; use Symfony\Component\Finder\Shell\Command; +use Symfony\Component\Finder\Iterator\SortableIterator; +use Symfony\Component\Finder\Expression\Expression; /** * Shell engine implementation using GNU find command. @@ -32,8 +34,29 @@ public function getName() /** * {@inheritdoc} */ - protected function buildFormatSorting(Command $command, $format) + protected function buildFormatSorting(Command $command, $sort) { + switch ($sort) { + case SortableIterator::SORT_BY_NAME: + $command->ins('sort')->add('| sort'); + + return; + case SortableIterator::SORT_BY_TYPE: + $format = '%y'; + break; + case SortableIterator::SORT_BY_ACCESSED_TIME: + $format = '%A@'; + break; + case SortableIterator::SORT_BY_CHANGED_TIME: + $format = '%C@'; + break; + case SortableIterator::SORT_BY_MODIFIED_TIME: + $format = '%T@'; + break; + default: + throw new \InvalidArgumentException('Unknown sort options: '.$sort.'.'); + } + $command ->get('find') ->add('-printf') @@ -59,4 +82,21 @@ protected function buildFindCommand(Command $command, $dir) { return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended'); } + + /** + * {@inheritdoc} + */ + protected function buildContentFiltering(Command $command, array $contains, $not = false) + { + foreach ($contains as $contain) { + $expr = Expression::create($contain); + + // todo: avoid forking process for each $pattern by using multiple -e options + $command + ->add('| xargs -r grep -I') + ->add($expr->isCaseSensitive() ? null : '-i') + ->add($not ? '-L' : '-l') + ->add('-Ee')->arg($expr->renderPattern()); + } + } } diff --git a/src/Symfony/Component/Finder/Shell/Command.php b/src/Symfony/Component/Finder/Shell/Command.php index fb4714f26b3b..ac285661ceee 100644 --- a/src/Symfony/Component/Finder/Shell/Command.php +++ b/src/Symfony/Component/Finder/Shell/Command.php @@ -246,4 +246,17 @@ public function join() function($bit) { return null !== $bit; } )); } + + /** + * Insert a string or a Command instance before the bit at given position $index (index starts from 0). + * + * @param string|Command $bit + * + * @return Command The current Command instance + */ + public function addAtIndex($bit, $index) + { + array_splice($this->bits, $index, 0, $bit); + return $this; + } } diff --git a/src/Symfony/Component/Finder/Tests/FinderTest.php b/src/Symfony/Component/Finder/Tests/FinderTest.php index 143cff2fde0f..dcc8bb95bd01 100644 --- a/src/Symfony/Component/Finder/Tests/FinderTest.php +++ b/src/Symfony/Component/Finder/Tests/FinderTest.php @@ -23,7 +23,7 @@ public static function setUpBeforeClass() { parent::setUpBeforeClass(); - self::$tmpDir = sys_get_temp_dir().'/symfony2_finder'; + self::$tmpDir = realpath(sys_get_temp_dir().'/symfony2_finder'); } public function testCreate()