I want to use PHP to read all files and paths ignored by .gitignore configuration. Just like how git does.
It's possible to read directory repeatedly and use regular expression for each file to filter. But it`s so ineffective if the path have too much files.
Any good and most effective way to read target files and path ignored by .gitignore?
You need to proceed in several steps:
Each folder can have one, so don't assume there's a single one.
And submodules have a .git link to the main .git folder, so be wary about stopping too early as well.
It'll go something like:
function find_gitignore_files($dir) {
$files = array();
while (true) {
$file = "$dir/.gitignore";
if (is_file($file)) $files[] = $file;
if (is_dir("$dir/.git") && !is_link("$dir/.git")) break; # stop here
if (dirname($dir) === '.') break; # and here
$dir = dirname($dir);
}
return $files;
}
You need to ignore comments, mind the negation operator (!
), and mind the globs.
This one is, give or take, is going to go something like:
function parse_git_ignore_file($file) { # $file = '/absolute/path/to/.gitignore'
$dir = dirname($file);
$matches = array();
$lines = file($file);
foreach ($lines as $line) {
$line = trim($line);
if ($line === '') continue; # empty line
if (substr($line, 0, 1) == '#') continue; # a comment
if (substr($line, 0, 1) == '!') { # negated glob
$line = substr($line, 1);
$files = array_diff(glob("$dir/*"), glob("$dir/$line"));
} else { # normal glob
$files = glob("$dir/$line");
}
$matches = array_merge($matches, $files);
}
return $matches;
}
(Note: none of the above is tested, but they should put you in the right direction.)
Just a crazy idea: if you rely on Git to give you the patterns for ignored files why not rely on it to give the list of included/ignored files? Just issue a command like:
git ls-files
for all tracked filesgit clean -ndX
or git ls-files -i --exclude-from=[Path_To_Your_Global].gitignore
for all ignored filesSee which Git command gives you the best output and then loop through the path files.
And a word of caution: take all the necessary precaution measures needed when executing external commands!
Sources:
I use this function to read the Whole path, it works good
function read_dir($dir)
{
$files = array();
$dir = preg_replace('~\/+~','/',$dir . '/');
$all = scandir($dir);
foreach($all as $path):
if($path !== '.' && $path !== '..'):
$path = $dir . '/' . $path;
$path = preg_replace('~\/+~','/',$path);
$path = realpath($path);
if(is_dir($path)):
$files = array_merge($files, read_dir($path));
endif;
$files[] = preg_replace('~/+~i','/',$path);
endif;
endforeach;
return $files;
}
UPDATE: You Can Use preg_grep over the above function as follow
$files = preg_grep('~\.gitignore\b~i', array_values(read_dir($path)));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With