diff --git a/features/distignore.feature b/features/distignore.feature index d74bda1..bb5279e 100644 --- a/features/distignore.feature +++ b/features/distignore.feature @@ -385,3 +385,23 @@ Feature: Generate a distribution archive of a project | targz | tar.gz | tar -zxvf | foo | | zip | zip | unzip | bar7 | | targz | tar.gz | tar -zxvf | bar8 | + + Scenario: Does not crash when a broken symlink is encountered + # @see https://github.com/wp-cli/dist-archive-command/issues/86 + Given an empty directory + And an empty foo/target-directory directory + And a foo/.distignore file: + """ + """ + + When I run `ln -s {RUN_DIR}/foo/target-directory {RUN_DIR}/foo/symlink` + Then STDERR should be empty + + When I run `rm -rf {RUN_DIR}/foo/target-directory` + Then STDERR should be empty + + When I try `wp dist-archive foo` + Then STDERR should contain: + """ + Error: Broken symlink at /symlink. Target missing at + """ diff --git a/src/Dist_Archive_Command.php b/src/Dist_Archive_Command.php index ac71d48..f4c66dc 100644 --- a/src/Dist_Archive_Command.php +++ b/src/Dist_Archive_Command.php @@ -484,10 +484,18 @@ private function get_file_list( $source_dir_path, $excluded = false ) { */ foreach ( $iterator as $item ) { $relative_filepath = str_replace( $source_dir_path, '', $item->getPathname() ); - if ( $this->checker->isPathIgnored( $relative_filepath ) ) { - $excluded_files[] = $relative_filepath; - } else { - $included_files[] = $relative_filepath; + try { + if ( $this->checker->isPathIgnored( $relative_filepath ) ) { + $excluded_files[] = $relative_filepath; + } else { + $included_files[] = $relative_filepath; + } + } catch ( \Inmarelibero\GitIgnoreChecker\Exception\InvalidArgumentException $exception ) { + if ( $item->isLink() && ! file_exists( readlink( $item->getPathname() ) ) ) { + WP_CLI::error( "Broken symlink at {$relative_filepath}. Target missing at {$item->getLinkTarget()}." ); + } else { + WP_CLI::error( $exception->getMessage() ); + } } }