From 36edba9400e12ca8a7e7febf97093bd00f360255 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 23 Jul 2019 11:50:41 +0200 Subject: [PATCH 1/7] Try adding some more tests for include/exclude --- tests/IterableCodeExtractorTest.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/IterableCodeExtractorTest.php b/tests/IterableCodeExtractorTest.php index bdca27f3..a147df42 100644 --- a/tests/IterableCodeExtractorTest.php +++ b/tests/IterableCodeExtractorTest.php @@ -110,4 +110,28 @@ public function test_can_override_exclude_by_include() { $expected = static::$base . 'foo/bar/excluded/ignored.js'; $this->assertContains( $expected, $result ); } + + public function test_can_include_file_in_excluded_folder() { + $includes = [ 'vendor/vendor-file.php' ]; + $excludes = [ 'vendor' ]; + $result = IterableCodeExtractor::getFilesFromDirectory( self::$base, $includes, $excludes, [ 'php', 'js' ] ); + $expected = static::$base . 'vendor/vendor-file.php'; + $this->assertContains( $expected, $result ); + } + + public function test_can_include_file_in_excluded_folder_with_leading_slash() { + $includes = [ '/vendor/vendor-file.php' ]; + $excludes = [ 'vendor' ]; + $result = IterableCodeExtractor::getFilesFromDirectory( self::$base, $includes, $excludes, [ 'php', 'js' ] ); + $expected = static::$base . 'vendor/vendor-file.php'; + $this->assertContains( $expected, $result ); + } + + public function test_can_include_file_in_excluded_folder_by_wildcard() { + $includes = [ 'vendor/**' ]; + $excludes = [ 'vendor' ]; + $result = IterableCodeExtractor::getFilesFromDirectory( self::$base, $includes, $excludes, [ 'php', 'js' ] ); + $expected = static::$base . 'vendor/vendor-file.php'; + $this->assertContains( $expected, $result ); + } } From 763941ad420d9448c51de738a9a40863d87cf362 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 23 Jul 2019 11:51:12 +0200 Subject: [PATCH 2/7] Trim leading slashes --- src/IterableCodeExtractor.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/IterableCodeExtractor.php b/src/IterableCodeExtractor.php index a0e9b148..8d2aa7c6 100644 --- a/src/IterableCodeExtractor.php +++ b/src/IterableCodeExtractor.php @@ -159,6 +159,7 @@ protected static function containsMatchingChildren( SplFileInfo $dir, array $mat /** @var string $root_relative_path */ $root_relative_path = str_replace( static::$dir, '', $dir->getPathname() ); + $root_relative_path = ltrim( $root_relative_path, '/' ); foreach ( $matchers as $path_or_file ) { // If the matcher contains no wildcards and the path matches the start of the matcher. From feeb9d8c5149275ff2c9cf1790e2e79d9044798e Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 23 Jul 2019 11:58:30 +0200 Subject: [PATCH 3/7] Fix gitignore file to not exclude nested vendor dirs --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4a485fb2..0af9abb9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ .DS_Store wp-cli.local.yml -node_modules/ -vendor/ +/node_modules +/vendor *.zip *.tar.gz *.swp From 3172ea7bbf00323f0df519af777fbf1a2bf879a2 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 23 Jul 2019 11:58:50 +0200 Subject: [PATCH 4/7] Add new test file --- tests/data/vendor/vendor-file.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/data/vendor/vendor-file.php diff --git a/tests/data/vendor/vendor-file.php b/tests/data/vendor/vendor-file.php new file mode 100644 index 00000000..e69de29b From ea60a20d5d9d677bf9ea05a359a01f199cca2f08 Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Tue, 13 Aug 2019 15:16:13 +0200 Subject: [PATCH 5/7] Add missing file to expected sorted array --- tests/IterableCodeExtractorTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/IterableCodeExtractorTest.php b/tests/IterableCodeExtractorTest.php index c64c623e..9f25cb46 100644 --- a/tests/IterableCodeExtractorTest.php +++ b/tests/IterableCodeExtractorTest.php @@ -120,6 +120,7 @@ public function test_can_return_all_directory_files_sorted() { static::$base . 'foo/bar/foo/bar/foo/bar/deep_directory_also_included.php', static::$base . 'foo/bar/foofoo/included.js', static::$base . 'hoge/should_NOT_be_included.js', + static::$base . 'vendor/vendor-file.php', ); $this->assertEquals( $expected, $result ); } From 5021e63397f44bd46797f8838b1806254f4feb4b Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Tue, 13 Aug 2019 15:53:16 +0200 Subject: [PATCH 6/7] Fix logic to include directories --- src/IterableCodeExtractor.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/IterableCodeExtractor.php b/src/IterableCodeExtractor.php index f2c286c8..11af44ec 100644 --- a/src/IterableCodeExtractor.php +++ b/src/IterableCodeExtractor.php @@ -159,9 +159,10 @@ protected static function containsMatchingChildren( SplFileInfo $dir, array $mat /** @var string $root_relative_path */ $root_relative_path = str_replace( static::$dir, '', $dir->getPathname() ); - $root_relative_path = ltrim( $root_relative_path, '/' ); foreach ( $matchers as $path_or_file ) { + $path_or_file = ltrim( $path_or_file, '/' ); + // If the matcher contains no wildcards and the path matches the start of the matcher. if ( '' !== $root_relative_path && @@ -205,19 +206,18 @@ public static function getFilesFromDirectory( $dir, array $include = [], array $ function ( $file, $key, $iterator ) use ( $include, $exclude, $extensions ) { /** @var RecursiveCallbackFilterIterator $iterator */ /** @var SplFileInfo $file */ - // If no $include is passed everything gets the weakest possible matching score. $inclusion_score = empty( $include ) ? 0.1 : static::calculateMatchScore( $file, $include ); $exclusion_score = static::calculateMatchScore( $file, $exclude ); // Always include directories that aren't excluded. - if ( 0 === $exclusion_score && $iterator->hasChildren() ) { + if ( $file->isDir() && 0 === $exclusion_score ) { return true; } - if ( 0 === $inclusion_score || $exclusion_score > $inclusion_score ) { + if ( $file->isDir() && ( 0 === $inclusion_score || $exclusion_score > $inclusion_score ) ) { // Always include directories that may have matching children even if they are excluded. - return $iterator->hasChildren() && static::containsMatchingChildren( $file, $include ); + return static::containsMatchingChildren( $file, $include ); } return ( $file->isFile() && in_array( $file->getExtension(), $extensions, true ) ); From a5551a0b50ea9ac4dbcbaa451498c9ff971b47f6 Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Tue, 13 Aug 2019 16:55:40 +0200 Subject: [PATCH 7/7] Another try at fixing the include/exclude logic --- src/IterableCodeExtractor.php | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/IterableCodeExtractor.php b/src/IterableCodeExtractor.php index 11af44ec..f0206ebe 100644 --- a/src/IterableCodeExtractor.php +++ b/src/IterableCodeExtractor.php @@ -161,8 +161,6 @@ protected static function containsMatchingChildren( SplFileInfo $dir, array $mat $root_relative_path = str_replace( static::$dir, '', $dir->getPathname() ); foreach ( $matchers as $path_or_file ) { - $path_or_file = ltrim( $path_or_file, '/' ); - // If the matcher contains no wildcards and the path matches the start of the matcher. if ( '' !== $root_relative_path && @@ -206,21 +204,26 @@ public static function getFilesFromDirectory( $dir, array $include = [], array $ function ( $file, $key, $iterator ) use ( $include, $exclude, $extensions ) { /** @var RecursiveCallbackFilterIterator $iterator */ /** @var SplFileInfo $file */ + + // Normalize include and exclude paths. + $include = array_map( 'static::trim_leading_slash', $include ); + $exclude = array_map( 'static::trim_leading_slash', $exclude ); + // If no $include is passed everything gets the weakest possible matching score. $inclusion_score = empty( $include ) ? 0.1 : static::calculateMatchScore( $file, $include ); $exclusion_score = static::calculateMatchScore( $file, $exclude ); // Always include directories that aren't excluded. - if ( $file->isDir() && 0 === $exclusion_score ) { + if ( 0 === $exclusion_score && $iterator->hasChildren() ) { return true; } - if ( $file->isDir() && ( 0 === $inclusion_score || $exclusion_score > $inclusion_score ) ) { + if ( ( 0 === $inclusion_score || $exclusion_score > $inclusion_score ) && $iterator->hasChildren() ) { // Always include directories that may have matching children even if they are excluded. return static::containsMatchingChildren( $file, $include ); } - return ( $file->isFile() && in_array( $file->getExtension(), $extensions, true ) ); + return ( ( $inclusion_score >= $exclusion_score ) && $file->isFile() && in_array( $file->getExtension(), $extensions, true ) ); } ), RecursiveIteratorIterator::CHILD_FIRST @@ -239,4 +242,14 @@ function ( $file, $key, $iterator ) use ( $include, $exclude, $extensions ) { return $filtered_files; } + + /** + * Trim leading slash from a path. + * + * @param string $path Path to trim. + * @return string Trimmed path. + */ + private static function trim_leading_slash( $path ) { + return ltrim( $path, '/' ); + } }