Skip to content

Instantly share code, notes, and snippets.

@eliashaeussler
Last active November 18, 2020 17:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eliashaeussler/29f39d318b78c096e19170acb483b09d to your computer and use it in GitHub Desktop.
Save eliashaeussler/29f39d318b78c096e19170acb483b09d to your computer and use it in GitHub Desktop.
Filter by Git repositories in Symfony Finder
<?php
declare(strict_types=!);
$filter = new \EliasHaeussler\App\Filter('app');
$finder = \Symfony\Component\Finder\Finder::create()
->in($filter->getBasePath())
->filter($filter->repositories());
foreach ($finder as $file) {
echo 'Hello, my name is ' . $file->getBasename() . '!';
}
<?php
declare(strict_types=1);
namespace EliasHaeussler\App;
/*
* Copyright (C) 2020 Elias Häußler <elias@haeussler.dev>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Filter class for use in combination with {@see \Symfony\Component\Finder\Finder::filter()}.
*
* @author Elias Häußler <elias@haeussler.dev>
* @license GPL-3.0-or-later
*/
final class Filter
{
/**
* @var string[]
*/
private static $knownRepositories = [];
/**
* @var string
*/
private $basePath;
public function __construct(string $basePath)
{
$this->basePath = $basePath;
}
/**
* Build closure to filter for files in repositories only.
*
* @return \Closure
*/
public function repositories(): \Closure
{
return function (\SplFileInfo $file): bool {
if ($this->isWithinKnownRepository($file)) {
return true;
}
if ($this->isWithinRepository($file)) {
static::$knownRepositories[] = $this->determineBaseDirectory($file);
return true;
}
return false;
};
}
/**
* Test whether a given file is located inside a known repository.
*
* @param \SplFileInfo $file
* @return bool
*/
private function isWithinKnownRepository(\SplFileInfo $file): bool
{
$realPath = rtrim($file->getRealPath(), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
foreach (static::$knownRepositories as $knownRepository) {
if (strpos($realPath, rtrim($knownRepository, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR) === 0) {
return true;
}
}
return false;
}
/**
* Test whether a given file is located inside a Git repository.
*
* @param \SplFileInfo $file
* @return bool
*/
private function isWithinRepository(\SplFileInfo $file): bool
{
if (strpos($file->getRealPath(), $this->basePath) !== 0) {
return false;
}
return file_exists(static::determineBaseDirectory($file) . DIRECTORY_SEPARATOR . '.git');
}
/**
* Determine base directory of a given file within the current base path.
*
* @param \SplFileInfo $file
* @return string
*/
private function determineBaseDirectory(\SplFileInfo $file): string
{
$absolutePath = ltrim(substr($file->getRealPath(), strlen($this->basePath)), DIRECTORY_SEPARATOR);
$repositoryName = explode(DIRECTORY_SEPARATOR, $absolutePath)[0];
return rtrim($this->basePath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $repositoryName;
}
public function getBasePath(): string
{
return $this->basePath;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment