1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
#!/usr/bin/env php
<?php
ini_set("log_errors", false);
ini_set("display_errors", true);
if ($argc > 1) {
if ($argv[1] === "-") {
$file = "php://stdin";
} else {
$file = $argv[1];
}
} elseif (stdin_is_readable()) {
$file = "php://stdin";
} else {
$file = "./package.xml";
}
if (($xml = simplexml_load_file($file))) {
$xml_files = xmllist($xml->contents[0]);
$dirs = ["."];
while ($dir = array_shift($dirs)) {
foreach (dirlist($dir) as $file) {
if (is_gitignored($file)) {
continue;
}
if (is_commonly_ignored($file)) {
continue;
}
if (!is_dir($file)) {
if (!in_array($file, $xml_files)) {
echo "Missing file $file\n";
}
} else {
$base = basename($file);
if ($base{0} !== ".") {
array_push($dirs, $file);
}
}
}
}
foreach ($xml_files as $file) {
if (!file_exists($file)) {
echo "Extraneous file $file\n";
}
}
}
###
function error($fmt) {
trigger_error(call_user_func_array("sprintf", func_get_args()));
}
function stdin_is_readable() {
$r = [STDIN]; $w = $e = [];
return stream_select($r, $w, $e, 0);
}
function is_gitignored($file) {
static $gitignore, $gitmodules;
if (!isset($gitmodules)) {
if (is_readable("./.gitmodules")) {
$gitmodules = explode("\n", `git submodule status | awk '{printf$2}'`);
} else {
$gitmodules = false;
}
}
if (!isset($gitignore)) {
if (is_readable("./.gitignore")) {
$ignore_submodules = $gitmodules ? " ! -path './".implode("/*' ! -path './", $gitmodules)."/*'" : "";
$gitignore = explode("\n", `find . $ignore_submodules | git check-ignore --stdin`);
} else {
$gitignore = false;
}
}
if ($gitignore) {
if (in_array($file, $gitignore)) {
return true;
}
}
if ($gitmodules) {
foreach ($gitmodules as $module) {
if (fnmatch("./$module/*", $file)) {
return true;
}
}
}
return false;
}
function is_commonly_ignored($file) {
return fnmatch("./.git*", $file)
|| in_array($file, ["./package.xml", "./package2.xml", "./.travis.yml", "./.editorconfig"], true);
}
function xmllist(SimpleXmlElement $dir, $p = ".", &$a = null) {
settype($a, "array");
$p = trim($p, "/") . "/" . trim($dir["name"], "/") . "/";
foreach ($dir as $file) {
switch ($file->getName()) {
case "dir":
xmllist($file, $p, $a);
break;
case "file":
$a[] = sprintf("%s/%s", trim($p, "/"), trim($file["name"]));
break;
default:
error("Unknown content type: %s", $file->getName());
break;
}
}
return $a;
}
function dirlist($dir, $p = null) {
$p = implode("/", array_filter([trim($p, "/"), trim($dir, "/")]));
foreach (scandir($p) as $file) {
yield $p."/".$file;
}
}
|