index/tools/update-headers

174 lines
5 KiB
PHP
Executable file

#!/usr/bin/env php
<?php
// this file sucks, screws up the header if incomplete
// successfully corrects filenames though
// fix this if you ever feel like it, or don't
date_default_timezone_set('utc');
function git_changes(): array {
$files = [];
$dir = getcwd();
try {
chdir(__DIR__ . '/..');
$output = explode("\n", trim(shell_exec('git status --short --porcelain=v1 --untracked-files=all --no-column')));
foreach($output as $line) {
$line = trim($line);
$file = realpath(explode(' ', $line)[1]);
$files[] = $file;
}
} finally {
chdir($dir);
}
return $files;
}
function collect_files(string $directory): array {
$files = [];
$dir = glob(realpath($directory) . DIRECTORY_SEPARATOR . '*');
foreach($dir as $file) {
if(is_dir($file)) {
$files = array_merge($files, collect_files($file));
continue;
}
$files[] = $file;
}
return $files;
}
echo 'Indexing changed files according to git...' . PHP_EOL;
$changed = git_changes();
echo 'Collecting files...' . PHP_EOL;
$sources = collect_files(__DIR__ . '/../src');
$tests = collect_files(__DIR__ . '/../tests');
$files = array_merge($sources, $tests);
$topDir = dirname(__DIR__) . DIRECTORY_SEPARATOR;
$now = gmdate('Y-m-d');
foreach($files as $file) {
echo 'Scanning ' . str_replace($topDir, '', $file) . '...' . PHP_EOL;
try {
$handle = fopen($file, 'rb');
$checkPHP = trim(fgets($handle)) === '<?php';
if(!$checkPHP) {
echo 'File is not PHP.' . PHP_EOL;
continue;
}
$headerLines = [];
$expectLine = '// ' . basename($file);
$nameLine = trim(fgets($handle));
if($nameLine !== $expectLine) {
echo ' File name is missing or invalid, queuing update...' . PHP_EOL;
$headerLines['name'] = $expectLine;
}
$createdPrefix = '// Created: ';
$createdLine = trim(fgets($handle));
if(strpos($createdLine, $createdPrefix) !== 0) {
echo ' Creation date is missing, queuing update...' . PHP_EOL;
$headerLines['created'] = $createdPrefix . $now;
}
$updatedPrefix = '// Updated: ';
$updatedLine = trim(fgets($handle));
$updatedDate = substr($updatedLine, strlen($updatedPrefix));
if(strpos($updatedLine, $updatedPrefix) !== 0 || (in_array($file, $changed) && $updatedDate !== $now)) {
echo ' Updated date is inaccurate, queuing update...' . PHP_EOL;
$headerLines['updated'] = $updatedPrefix . $now;
}
$blankLine = trim(fgets($handle));
if(!empty($blankLine)) {
echo ' Trailing newline missing, queuing update...' . PHP_EOL;
$headerLines['blank'] = '';
}
if(!empty($headerLines)) {
fclose($handle);
try {
$tmpName = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'ndx-uh-' . bin2hex(random_bytes(8)) . '.tmp';
copy($file, $tmpName);
$read = fopen($tmpName, 'rb');
$handle = fopen($file, 'wb');
fwrite($handle, fgets($read));
$insertAfter = [];
if(empty($headerLines['name']))
fwrite($handle, fgets($read));
else {
$line = fgets($read);
if(strpos($line, '// ') !== 0)
$insertAfter[] = $line;
fwrite($handle, $headerLines['name'] . "\n");
}
if(empty($headerLines['created']))
fwrite($handle, fgets($read));
else {
$line = fgets($read);
if(strpos($line, '// Created: ') !== 0)
$insertAfter[] = $line;
fwrite($handle, $headerLines['created'] . "\n");
}
if(empty($headerLines['updated']))
fwrite($handle, fgets($read));
else {
$line = fgets($read);
if(strpos($line, '// Updated: ') !== 0)
$insertAfter[] = $line;
fwrite($handle, $headerLines['updated'] . "\n");
}
if(!isset($headerLines['blank']))
fwrite($handle, fgets($read));
else {
$line = fgets($read);
if(!empty($line)) {
$insertAfter[] = $line;
fwrite($handle, "\n");
}
}
foreach($insertAfter as $line)
fwrite($handle, $line);
while(($line = fgets($read)) !== false)
fwrite($handle, $line);
} finally {
if(is_resource($read))
fclose($read);
if(is_file($tmpName))
unlink($tmpName);
}
}
} finally {
fclose($handle);
}
}