Skip to content

Commit d749077

Browse files
committed
Support for exclude directories
1 parent ee3f1c1 commit d749077

File tree

5 files changed

+210
-31
lines changed

5 files changed

+210
-31
lines changed

parallel-lint.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ function showOptions()
1414
?>
1515
Options:
1616
-p <php> Specify PHP-CGI executable to run.
17-
-short Set short_open_tag to On (default Off)
18-
-asp Set asp_tags to On (default Off)
19-
-e <ext> Check only files with selected extension separated by comma (default: php,php3,php4,php5,phtml)
17+
-s, --short Set short_open_tag to On (default Off)
18+
-a, -asp Set asp_tags to On (default Off)
19+
-e <ext> Check only files with selected extensions separated by comma
20+
(default: php,php3,php4,php5,phtml)
21+
--exclude Exclude directory. If you want exclude multiple directory, use
22+
multiple exclude parameters.
2023
-j <num> Run <num> jobs in parallel (default 10)
2124
-h, --help Print this help.
2225
<?php
@@ -26,10 +29,10 @@ function showOptions()
2629
* Help
2730
*/
2831
if (!isset($_SERVER['argv'][1]) || in_array('-h', $_SERVER['argv']) || in_array('--help', $_SERVER['argv'])) { ?>
29-
PHP Parallel Lint version 0.2
32+
PHP Parallel Lint version 0.3
3033
---------------------------
3134
Usage:
32-
parallel-lint [options] [files or directories separated by space]
35+
parallel-lint [sa] [-p php] [-e ext] [-j num] [--exclude dir] [files or directories]
3336
<?php
3437
showOptions();
3538
exit;

src/Manager.php

Lines changed: 178 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,13 @@
3030
either expressed or implied, of the FreeBSD Project.
3131
*/
3232

33+
3334
require_once __DIR__ . '/exceptions.php';
3435
require_once __DIR__ . '/Settings.php';
3536
require_once __DIR__ . '/Process.php';
3637
require_once __DIR__ . '/Output.php';
3738
require_once __DIR__ . '/Error.php';
3839

39-
40-
class ArrayIterator extends \ArrayIterator
41-
{
42-
public function getNext()
43-
{
44-
$this->next();
45-
return $this->current();
46-
}
47-
}
48-
4940
class Manager
5041
{
5142
const CODE_OK = 0,
@@ -58,6 +49,7 @@ class Manager
5849
* @param array $arguments
5950
* @return Settings
6051
* @throws InvalidArgumentException
52+
* @throws Exception
6153
*/
6254
public function parseArguments(array $arguments)
6355
{
@@ -68,24 +60,30 @@ public function parseArguments(array $arguments)
6860
if ($argument{0} !== '-') {
6961
$setting->paths[] = $argument;
7062
} else {
71-
switch (substr($argument, 1)) {
72-
case 'p':
63+
switch ($argument) {
64+
case '-p':
7365
$setting->phpExecutable = $arguments->getNext();
7466
break;
7567

76-
case 'short':
68+
case '-s':
69+
case '--short':
7770
$setting->shortTag = true;
7871
break;
7972

80-
case 'asp':
73+
case '-a':
74+
case '--asp':
8175
$setting->aspTags = true;
8276
break;
8377

84-
case 'e':
78+
case '--exclude':
79+
$setting->excluded[] = $arguments->getNext();
80+
break;
81+
82+
case '-e':
8583
$setting->extensions = array_map('trim', explode(',', $arguments->getNext()));
8684
break;
8785

88-
case 'j':
86+
case '-j':
8987
$setting->parallelJobs = max((int) $arguments->getNext(), 1);
9088
break;
9189

@@ -95,6 +93,10 @@ public function parseArguments(array $arguments)
9593
}
9694
}
9795

96+
if (empty($setting->paths)) {
97+
throw new Exception('No path set.');
98+
}
99+
98100
return $setting;
99101
}
100102

@@ -106,13 +108,17 @@ public function parseArguments(array $arguments)
106108
public function run(Settings $settings = null)
107109
{
108110
$settings = $settings ?: new Settings;
111+
$output = $this->output ?: new Output(new ConsoleWriter);
109112

110113
$this->checkPhpExecutableExists($settings->phpExecutable);
111114

112115
$cmdLine = $this->getCmdLine($settings);
113-
$files = $this->getFilesFromPaths($settings->paths, $settings->extensions);
116+
$files = $this->getFilesFromPaths($settings->paths, $settings->extensions, $settings->excluded);
117+
118+
if (empty($files)) {
119+
throw new Exception('No file found to check.');
120+
}
114121

115-
$output = $this->output ?: new Output(new ConsoleWriter);
116122
$output->setTotalFileCount(count($files));
117123

118124
/** @var LintProcess[] $running */
@@ -216,10 +222,11 @@ protected function getCmdLine(Settings $settings)
216222
/**
217223
* @param array $paths
218224
* @param array $extensions
225+
* @param array $excluded
219226
* @return array
220227
* @throws NotExistsPathException
221228
*/
222-
protected function getFilesFromPaths(array $paths, array $extensions)
229+
protected function getFilesFromPaths(array $paths, array $extensions, array $excluded = array())
223230
{
224231
$extensions = array_flip($extensions);
225232
$files = array();
@@ -228,11 +235,17 @@ protected function getFilesFromPaths(array $paths, array $extensions)
228235
if (is_file($path)) {
229236
$files[] = $path;
230237
} else if (is_dir($path)) {
231-
$directoryFiles = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path));
232-
foreach ($directoryFiles as $directoryFile) {
233-
$directoryFile = (string) $directoryFile;
234-
if (isset($extensions[pathinfo($directoryFile, PATHINFO_EXTENSION)])) {
235-
$files[] = $directoryFile;
238+
239+
$iterator = new \RecursiveDirectoryIterator($path);
240+
if (!empty($excluded)) {
241+
$iterator = new ExcludeRecursiveDirectoryIterator($iterator, $excluded);
242+
}
243+
$iterator = new \RecursiveIteratorIterator($iterator);
244+
245+
/** @var \SplFileInfo[] $iterator */
246+
foreach ($iterator as $directoryFile) {
247+
if (isset($extensions[$directoryFile->getExtension()])) {
248+
$files[] = (string) $directoryFile;
236249
}
237250
}
238251
} else {
@@ -242,4 +255,145 @@ protected function getFilesFromPaths(array $paths, array $extensions)
242255

243256
return $files;
244257
}
258+
}
259+
260+
class ArrayIterator extends \ArrayIterator
261+
{
262+
public function getNext()
263+
{
264+
$this->next();
265+
return $this->current();
266+
}
267+
}
268+
269+
class ExcludeRecursiveDirectoryIterator implements \RecursiveIterator
270+
{
271+
/** @var array */
272+
private $excluded = array();
273+
274+
/** @var \RecursiveDirectoryIterator */
275+
private $iterator;
276+
277+
/**
278+
* @param array $excluded
279+
* @param \RecursiveDirectoryIterator $iterator
280+
*/
281+
public function __construct(\RecursiveDirectoryIterator $iterator, array $excluded)
282+
{
283+
$this->iterator = $iterator;
284+
$this->excluded = array_map(array($this, 'normalizePath'), $excluded);
285+
}
286+
287+
/**
288+
* (PHP 5 &gt;= 5.0.0)<br/>
289+
* Return the current element
290+
* @link http://php.net/manual/en/iterator.current.php
291+
* @return mixed Can return any type.
292+
*/
293+
public function current()
294+
{
295+
return $this->iterator->current();
296+
}
297+
298+
/**
299+
* (PHP 5 &gt;= 5.0.0)<br/>
300+
* Move forward to next element
301+
* @link http://php.net/manual/en/iterator.next.php
302+
* @return void Any returned value is ignored.
303+
*/
304+
public function next()
305+
{
306+
$this->iterator->next();
307+
}
308+
309+
/**
310+
* (PHP 5 &gt;= 5.0.0)<br/>
311+
* Return the key of the current element
312+
* @link http://php.net/manual/en/iterator.key.php
313+
* @return mixed scalar on success, or null on failure.
314+
*/
315+
public function key()
316+
{
317+
return $this->iterator->key();
318+
}
319+
320+
/**
321+
* (PHP 5 &gt;= 5.0.0)<br/>
322+
* Checks if current position is valid
323+
* @link http://php.net/manual/en/iterator.valid.php
324+
* @return boolean The return value will be casted to boolean and then evaluated.
325+
* Returns true on success or false on failure.
326+
*/
327+
public function valid()
328+
{
329+
return $this->iterator->valid();
330+
}
331+
332+
/**
333+
* (PHP 5 &gt;= 5.0.0)<br/>
334+
* Rewind the Iterator to the first element
335+
* @link http://php.net/manual/en/iterator.rewind.php
336+
* @return void Any returned value is ignored.
337+
*/
338+
public function rewind()
339+
{
340+
$this->iterator->rewind();
341+
}
342+
343+
/**
344+
* (PHP 5 &gt;= 5.1.0)<br/>
345+
* Returns if an iterator can be created for the current entry.
346+
* @link http://php.net/manual/en/recursiveiterator.haschildren.php
347+
* @return bool true if the current entry can be iterated over, otherwise returns false.
348+
*/
349+
public function hasChildren()
350+
{
351+
$path = $this->normalizePath($this->iterator->getPathname());
352+
foreach ($this->excluded as $exc) {
353+
if (strpos($path, $exc) === 0) {
354+
return false;
355+
}
356+
}
357+
358+
return $this->iterator->hasChildren();
359+
}
360+
361+
/**
362+
* (PHP 5 &gt;= 5.1.0)<br/>
363+
* Returns an iterator for the current entry.
364+
* @link http://php.net/manual/en/recursiveiterator.getchildren.php
365+
* @return \RecursiveIterator An iterator for the current entry.
366+
*/
367+
public function getChildren()
368+
{
369+
return new self($this->iterator->getChildren(), $this->excluded);
370+
}
371+
372+
373+
/**
374+
* Source: http://stackoverflow.com/questions/4774116/c-realpath-without-resolving-symlinks
375+
* @param string $path
376+
* @return string
377+
*/
378+
private function normalizePath($path)
379+
{
380+
if (!isset($path[0]) || $path[0] !== DIRECTORY_SEPARATOR) {
381+
$result = explode(DIRECTORY_SEPARATOR, getcwd());
382+
} else {
383+
$result = array('');
384+
}
385+
386+
$parts = explode(DIRECTORY_SEPARATOR, $path);
387+
foreach($parts as $part) {
388+
if ($part === '' || $part === '.') {
389+
continue;
390+
} if ($part === '..') {
391+
array_pop($result);
392+
} else {
393+
$result[] = $part;
394+
}
395+
}
396+
397+
return implode(DIRECTORY_SEPARATOR, $result);
398+
}
245399
}

src/Output.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,17 @@ interface IWriter
123123
public function write($string);
124124
}
125125

126+
class NullWriter implements IWriter
127+
{
128+
/**
129+
* @param string $string
130+
*/
131+
public function write($string)
132+
{
133+
134+
}
135+
}
136+
126137
class ConsoleWriter implements IWriter
127138
{
128139
/**

src/Settings.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,10 @@ class Settings
6767
* @var array
6868
*/
6969
public $paths = array();
70+
71+
/**
72+
* Dont't check files or directories
73+
* @var array
74+
*/
75+
public $excluded = array();
7076
}

src/exceptions.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,12 @@
3030
either expressed or implied, of the FreeBSD Project.
3131
*/
3232

33-
class InvalidArgumentException extends \Exception
33+
class Exception extends \Exception
34+
{
35+
36+
}
37+
38+
class InvalidArgumentException extends Exception
3439
{
3540
protected $argument;
3641

@@ -46,7 +51,7 @@ public function getArgument()
4651
}
4752
}
4853

49-
class NotExistsPathException extends \Exception
54+
class NotExistsPathException extends Exception
5055
{
5156
protected $path;
5257

0 commit comments

Comments
 (0)