From bde87e367298add197ec7f20cb94ff56719e4286 Mon Sep 17 00:00:00 2001 From: didou Date: Tue, 13 Apr 2004 16:24:12 +0000 Subject: [PATCH] add the revcheck script (tm) --- docs/scripts/revcheck.php | 941 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 941 insertions(+) create mode 100755 docs/scripts/revcheck.php diff --git a/docs/scripts/revcheck.php b/docs/scripts/revcheck.php new file mode 100755 index 00000000..e30de9cc --- /dev/null +++ b/docs/scripts/revcheck.php @@ -0,0 +1,941 @@ +#!/usr/bin/php -q + | + | Gabor Hojtsy | + | Mark Kronsbein | + | Jan Fabry + +----------------------------------------------------------------------+ +*/ +if ($argc < 2 || $argc > 3) { +?> + +Check the revision of translated files against +the actual english xml files, and print statistics + + Usage: + [] [>] + + must be a valid language code used + in the repository + + If you specify , the script only checks + the files maintained by the person you add here + + If you specify >, the output is an html file. + + Read more about Revision comments and related + funcionality in the PHP Documentation Howto. + + Authors: Thomas Schöfbeck + Gabor Hojtsy + Mark Kronsbein + Jan Fabry + + "act", + REV_NOREV => "norev", + REV_CRITICAL => "crit", + REV_OLD => "old", + REV_NOTAG => "wip", + REV_NOTRANS => "wip", + REV_CREDIT => "wip", + REV_WIP => "wip", +); + +// Option for the link to cvs.php.net: normal: "&f=h" +// long diff: "&f=h&num=10", unified (text): "&f=u" +define("CVS_OPT", "&f=h&num=10"); + +// Initializing variables from parameters +$LANG = $argv[1]; +if ($argc == 3) { + $MAINT = $argv[2]; +} else { + $MAINT = ""; +} + +// Main directory of the PHP documentation (depends on the +// sapi used). We do need the trailing slash! +if ("cli" === php_sapi_name()) { + if (isset($PHPDOCDIR) && is_dir($PHPDOCDIR)) + $DOCDIR = $PHPDOCDIR."/"; + else + $DOCDIR = "./"; +} else + $DOCDIR = "../"; + +// ========================================================================= +// Functions to get revision info and credits from a file +// ========================================================================= + +// Grabs the revision tag and stores credits from the file given +function get_tags($file, $val = "en-rev") +{ + // Read the first 500 chars. The comment should be at + // the begining of the file + $fp = @fopen($file, "r") or die ("Unable to read $file."); + $line = fread($fp, 500); + fclose($fp); + + // Check for English CVS revision tag (. is for $ in the preg!), + // Return if this was needed (it should be there) + if ($val == "en-rev") { + preg_match("//", $line, $match); + return $match[1]; + } + + // Handle credits (only if no maintainer is specified) + if ($val == "\\S*") { + + global $files_by_maint; + + // Find credits info, let more credits then one, + // using commas as list separator + if (preg_match("''U", $line, $match_credit)) { + + // Explode with commas a separators + $credits = explode(",", $match_credit[1]); + + // Store all elements + foreach ($credits as $num => $credit) { + $files_by_maint[trim($credit)][REV_CREDIT]++; + } + + } + } + + // No match before the preg + $match = array(); + + // Check for the translations "revision tag" + preg_match ("//U", + $line, + $match + ); + + // The tag with revision number is not found so search + // for n/a revision comment (comment where revision is not known) + if (count($match) == 0) { + preg_match ("''U", + $line, + $match + ); + } + + // Return with found revision info (number, maint, status) + return $match; + +} // get_tags() function end + + +// ========================================================================= +// Functions to check file status in translated directory, and store info +// ========================================================================= + +// Checks a file, and gather status info +function get_file_status($file) +{ + // The information is contained in these global arrays and vars + global $DOCDIR, $LANG, $MAINT, $files_by_mark, $files_by_maint; + global $file_sizes_by_mark; + global $missing_files, $missing_tags, $using_rev; + + // Transform english file name to translated file name + $trans_file = preg_replace("'^".$DOCDIR."en/'", $DOCDIR.$LANG."/", $file); + + // If we cannot find the file, we push it into the missing files list + if (!@file_exists($trans_file)) { + $files_by_mark[REV_NOTRANS]++; + $trans_name = substr($trans_file, strlen($DOCDIR) + strlen($LANG) + 1); + $size = round(filesize($file)/1024, 1); + $missing_files[$trans_name] = array( $size ); + $file_sizes_by_mark[REV_NOTRANS] += $size; + // compute en-tags just if they're needed in the WIP-Table + if($using_rev) { + $missing_files[$trans_name][] = "1.".get_tags($file); + } + return FALSE; + } + + // No specific maintainer, check for a revision tag + if (empty($MAINT)) { + $trans_tag = get_tags($trans_file, "\\S*"); + } + // If we need to check for a specific translator + else { + // Get translated files tag, with maintainer + $trans_tag = get_tags($trans_file, $MAINT); + + // If this is a file belonging to another + // maintainer, than we would not like to + // deal with it anymore + if (count($trans_tag) == 0) { + $trans_tag = get_tags($trans_file, "\\S*"); + // We found a tag for another maintainer + if (count($trans_tag) > 0) { + return FALSE; + } + } + } + + // Compute sizes and diffs + $en_size = intval(filesize($file) / 1024); + $trans_size = intval(filesize($trans_file) / 1024); + $size_diff = intval($en_size) - intval($trans_size); + + // If we found no revision tag, then collect this + // file in the missing tags list + if (count($trans_tag) == 0) { + $files_by_mark[REV_NOTAG]++; + $file_sizes_by_mark[REV_NOTAG] += $en_size; + $missing_tags[] = array(substr($trans_file, strlen($DOCDIR)), $en_size, $trans_size, $size_diff); + return FALSE; + } + + // Distribute values in separate vars for further processing + list(, $this_rev, $this_maint, $this_status) = $trans_tag; + + // Get English file revision + $en_rev = get_tags($file); + + // If we have a numeric revision number (not n/a), compute rev. diff + if (is_numeric($this_rev)) { + $rev_diff = intval($en_rev) - intval($this_rev); + $trans_rev = "1." . $this_rev; + $en_rev = "1." . $en_rev; + } else { + // If we have no numeric revision, make all revision + // columns hold the rev from the translated file + $rev_diff = $trans_rev = $this_rev; + $en_rev = "1." . $en_rev; + } + + // If the file is up-to-date + if ($rev_diff === 0) { + // Store file by status and maintainer + $files_by_mark[REV_UPTODATE]++; + $files_by_maint[$this_maint][REV_UPTODATE]++; + $file_sizes_by_mark[REV_UPTODATE] += $en_size; + + return FALSE; + } + + // Compute times and diffs + $en_date = intval((time() - filemtime($file)) / 86400); + $trans_date = intval((time() - filemtime($trans_file)) / 86400); + $date_diff = $en_date - $trans_date; + + // Make decision on file category by revision, date and size + if ($rev_diff >= ALERT_REV || $size_diff >= ALERT_SIZE || $date_diff <= ALERT_DATE) { + $status_mark = REV_CRITICAL; + } elseif ($rev_diff === "n/a") { + $status_mark = REV_NOREV; + } else { + $status_mark = REV_OLD; + } + + // Store files by status, and by maintainer too + $files_by_mark[$status_mark]++; + $files_by_maint[$this_maint][$status_mark]++; + $file_sizes_by_mark[$status_mark] += $en_size; + + return array( + "full_name" => $file, + "short_name" => basename($trans_file), + "revision" => array($en_rev, $trans_rev, $rev_diff), + "size" => array($en_size, $trans_size, $size_diff), + "date" => array($en_date, $trans_date, $date_diff), + "maintainer" => $this_maint, + "status" => $this_status, + "mark" => $status_mark + ); + +} // get_file_status() function end + +// ========================================================================= +// A function to check directory status in translated directory +// ========================================================================= + +// Check the status of files in a diretory of smarty/doc XML files +// The English directory is passed to this function to check +function get_dir_status($dir) +{ + + // Collect files and diretcories in these arrays + $directories = array(); + $files = array(); + + // Open the directory + $handle = @opendir($dir); + + // Walk through all names in the directory + while ($file = @readdir($handle)) { + + // If we found a file with one or two point as a name, + // or a CVS directory, skip the file + if (preg_match("/^\.{1,2}/",$file) || $file == 'CVS') + continue; + + // Collect files and directories + if (is_dir($dir.$file)) { $directories[] = $file; } + else { $files[] = $file; } + + } + + // Close the directory + @closedir($handle); + + // Sort files and directories + sort($directories); + sort($files); + + // Go through files first + $dir_status = array(); + foreach ($files as $file) { + // If the file status is OK, append the status info + if ($file_status = get_file_status($dir.$file)) { + $dir_status[] = $file_status; + } + } + + // Then go through subdirectories, merging all the info + // coming from subdirs to one array + foreach ($directories as $file) { + $dir_status = array_merge( + $dir_status, + get_dir_status($dir.$file.'/') + ); + } + + // Return with collected file info in + // this dir and subdirectories [if any] + return $dir_status; + +} // get_dir_status() function end + +// ========================================================================= +// Functions to read in the translation.xml file and process contents +// ========================================================================= + +// Get a multidimensional array with tag attributes +function parse_attr_string ($tags_attrs) +{ + $tag_attrs_processed = array(); + + // Go through the tag attributes + foreach($tags_attrs as $attrib_list) { + + // Get attr name and values + preg_match_all("!(.+)=\\s*([\"'])\\s*(.+)\\2!U", $attrib_list, $attribs); + + // Assign all attributes to one associative array + $attrib_array = array(); + foreach ($attribs[1] as $num => $attrname) { + $attrib_array[trim($attrname)] = trim($attribs[3][$num]); + } + + // Collect in order of tags received + $tag_attrs_processed[] = $attrib_array; + + } + + // Retrun with collected attributes + return $tag_attrs_processed; + +} // parse_attr_string() end + +// Parse the translation.xml file for +// translation related meta information +function parse_translation($DOCDIR, $LANG, $MAINT) +{ + global $files_by_mark; + + // Path to find translation.xml file, set default values, + // in case we can't find the translation file + $translation_xml = $DOCDIR.$LANG."/translation.xml"; + $output_charset = 'iso-8859-1'; + $translation = array( + "intro" => "", + "persons" => array(), + "files" => array(), + "allfiles" => array(), + ); + + // Check for file availability, return with default + // values, if we cannot find the file + if (!@file_exists($translation_xml)) { + return array($output_charset, $translation); + } + + // Else go on, and load in the file, replacing all + // space type chars with one space + $txml = join("", file($translation_xml)); + $txml = preg_replace("/\\s+/", " ", $txml); + + // Get intro text (different for a persons info and + // for a whole group info page) + if (empty($MAINT)) { + preg_match("!(.+)!s", $txml, $match); + $translation["intro"] = trim($match[1]); + } else { + $translation["intro"] = "Personal Statistics for ".$MAINT; + } + + // Get encoding for the output, from the translation.xml + // file encoding (should be the same as the used encoding + // in HTML) + preg_match("!<\?xml(.+)\?>!U", $txml, $match); + $xmlinfo = parse_attr_string($match); + $output_charset = $xmlinfo[1]["encoding"]; + + // Get persons list preg pattern, only check for a specific + // maintainer, if the users asked for it + if (empty($MAINT)) { + $pattern = "!!U"; + } else { + $pattern = "!!U"; + } + + // Find all persons matching the pattern + preg_match_all($pattern, $txml, $matches); + $translation['persons'] = parse_attr_string($matches[1]); + + // Get list of work in progress files + if (empty($MAINT)) { + + // Get all wip files + preg_match_all("!!U", $txml, $matches); + $translation['files'] = parse_attr_string($matches[1]); + + // Provide info about number of WIP files + $files_by_mark[REV_WIP] += count($translation['files']); + + } else { + + // Only check for a specific maintainer, if we were asked to + preg_match_all("!!U", $txml, $matches); + $translation['files'] = parse_attr_string($matches[1]); + + // Other maintainers wip files need to be cleared from + // available files list in the future, so store that info too. + preg_match_all("!!U", $txml, $matches); + $translation['allfiles'] = parse_attr_string($matches[1]); + + // Provide info about number of WIP files + $files_by_mark[REV_WIP] += count($translation['allfiles']); + + } + + // Return with collected info in two vars + return array($output_charset, $translation); + +} // parse_translation() function end() + +// ========================================================================= +// Debug functions for all the functions and code on this page +// ========================================================================= + +// Print preformatted (debug function) +function print_pre($var) +{ + print("
");
+    print_r($var);
+    print("
"); +} // print_pre() function end + +// ========================================================================= +// Start of the program execution +// ========================================================================= + +// Check for directory validity +if (!@is_dir($DOCDIR . $LANG)) { + die("The $LANG language code is not valid"); +} + +// Parse translation.xml file for more information +list($charset, $translation) = parse_translation($DOCDIR, $LANG, $MAINT); + +// Add WIP files to maintainers file count and figure out, +// if we need to use optional date and revision columns +$using_date = FALSE; $using_rev = FALSE; +foreach ($translation["files"] as $num => $fileinfo) { + $files_by_maint[$fileinfo["person"]][REV_WIP]++; + if (isset($fileinfo["date"])) { $using_date = TRUE; } + if (isset($fileinfo["revision"])) { $using_rev = TRUE; } +} + +// Get all files status +$files_status = get_dir_status($DOCDIR."en/"); + + +$navbar = "

Introduction | " . + "Translators | " . + "File summary by type | " . + "Files | "; +if (count($translation["files"]) != 0) + $navbar .= "Work in progress | "; +$navbar .= "Missing revision numbers | " . + "Untranslated files

\n"; + + +// Figure out generation date +$date = date("r"); + +// ========================================================================= +// Start of HTML page +// ========================================================================= + +print << + + +PHPDOC Revision-check + + + + + + +
+ + +

Status of the translated Smarty Manual

Generated: {$date}   /   Language: $LANG

+
+END_OF_MULTILINE; + +print ($navbar); + +// ========================================================================= +// Intro block goes here +// ========================================================================= + +// If we have an introduction text, print it out, with an anchor +if (!empty($translation["intro"])) { + print ''; + print '
' . + $translation['intro'] . '

'; +} + +// ========================================================================= +// Translators table goes here +// ========================================================================= + +// If person list available (valid translation.xml file in lang), print out +// the person list, with respect to the maintainer parameter specified +if (!empty($translation["persons"])) { + +print << + + + + + + + + + + + + + + + + + +END_OF_MULTILINE; + + // ' Please leave this comment here + + // We will collect the maintainers by nick here + $maint_by_nick = array(); + + // Print out a line for each maintainer (with respect to + // maintainer setting provided in command line) + foreach($translation["persons"] as $num => $person) { + + // Do not print out this person, if a + // specific maintainer info is asked for + if (!empty($MAINT) && $person["nick"] != $MAINT) { + continue; + } + + // Put maintaner number into associative array + // [Used in further tables for referencing] + $maint_by_nick[$person["nick"]] = $num; + + // Decide on the CVS text and the color of the line + if ($person["cvs"] === "yes") { + $cvsu = "x"; + $col = "old"; + } else { + $cvsu = " "; + $col = "wip"; + } + + // Try to do some antispam actions + $person["email"] = str_replace( + "@", + ":at:", + $person["email"] + ); + + // Get file info for this person + if (isset($files_by_maint[$person["nick"]])) { + $pi = $files_by_maint[$person["nick"]]; + } else { + $pi = array(); + } + + print("" . + "" . + "" . + "" . + "" . + "" . + "" . + "" . + "" . + "" . + "" . + "" . + "\n"); + } + + print "
Translator's nameContact emailNickC
V
S
Files maintained
cre-
dits
upto-
date
oldcri-
tical
no
rev
wipsum
$person[name]$person[email]$person[nick]$cvsu" . $pi[REV_CREDIT] . "" . $pi[REV_UPTODATE] . "" . $pi[REV_OLD] . "" . $pi[REV_CRITICAL] . "" . $pi[REV_NOREV] . "" . $pi[REV_WIP] . "" . array_sum($pi) . "
\n

 

\n"; +} + +// ========================================================================= +// Files summary table goes here +// ========================================================================= + +// Do not print out file summary table, if we are printing out a page +// for only one maintainer (his personal summary is in the table above) +if (empty($MAINT)) { + + print << + + + + + + + + +END_OF_MULTILINE; + + $files_sum = array_sum($files_by_mark); + $file_sizes_sum = array_sum($file_sizes_by_mark); + + $file_types = array( + array (REV_UPTODATE, "Up to date files"), + array (REV_OLD, "Old files"), + array (REV_CRITICAL, "Critical files"), + array (REV_WIP, "Work in progress"), + array (REV_NOREV, "Files without revision number"), + array (REV_NOTAG, "Files without revision tag"), + array (REV_NOTRANS, "Files available for translation") + ); + + foreach ($file_types as $num => $type) { + print "". + "". + "". + "". + "". + "\n"; + } + + print "\n". + "
File status typeNumber of filesPercent of filesSize of files (kB)Percent of size
".$type[1]."".intval($files_by_mark[$type[0]])."".number_format($files_by_mark[$type[0]] * 100 / $files_sum, 2 ). + "%".intval($file_sizes_by_mark[$type[0]])."".number_format($file_sizes_by_mark[$type[0]] * 100 / $file_sizes_sum, 2). + "%
Files total$files_sum100%$file_sizes_sum100%
\n

 

\n"; + +} + +print ($navbar."

 

\n"); + + +// ========================================================================= +// Files table goes here +// ========================================================================= + +print << + + + + + + + + + + + + + + + + + + + + +END_OF_MULTILINE; + +// This was the previous directory [first] +$prev_dir = $new_dir = $DOCDIR."en"; + +// Go through all files collected +foreach ($files_status as $num => $file) { + + // Make the maintainer a link, if we have that maintainer in the list + if (isset($maint_by_nick[$file["maintainer"]])) { + $file["maintainer"] = '' . $file["maintainer"] . ''; + } + + // If we have a 'numeric' revision diff and it is not zero, + // make a link to the CVS repository's diff script + if ($file["revision"][2] != "n/a" && $file["revision"][2] !== 0) { + $file["short_name"] = "" . $file["short_name"] . ""; + } + + // Guess the new directory from the full name of the file + $new_dir = dirname($file["full_name"]); + + // If this is a new directory, put out dir headline + if ($new_dir != $prev_dir) { + + // Drop out the unneeded parts from the dirname... + $display_dir = str_replace($DOCDIR."en/", "", dirname($file["full_name"])); + + // Print out directory header + print "\n"; + + // Store the new actual directory + $prev_dir = $new_dir; + } + + // Write out the line for the current file (get file name shorter) + print "". + "" . + "". + "". + "". + "". + "". + "". + "". + "". + "". + "\n"; + +} + +print("
Translated fileRevisionSize in kBAge in daysMaintainerStatus
en$LANGdiffen$LANGdiffen$LANGdiff
$display_dir
{$file['short_name']} {$file['revision'][0]} {$file['revision'][1]}{$file['revision'][2]} {$file['size'][0]} {$file['size'][1]} {$file['size'][2]} {$file['date'][0]} {$file['date'][1]} {$file['date'][2]} {$file['maintainer']}".trim($file['status'])."
\n

 

\n$navbar

 

\n"); + + +// ========================================================================= +// Work in progress table goes here +// ========================================================================= + +// If work-in-progress list is available (valid translation.xml file in lang) +if (count($translation["files"]) != 0) { + + // Print out files table header + print "\n" . + "\n" . + "". + "". + "". + ""; + + // Print out date and revision columns if needed + if ($using_date) { + print ''; + } + if ($using_rev) { + print '' . + ''; + } + print "\n"; + + // Go through files, and print out lines for them + foreach($translation["files"] as $num => $finfo) { + + // If we have a valid maintainer, link to the summary + if (isset($maint_by_nick[$finfo["person"]])) { + $finfo["person"] = '' . $finfo["person"] . ''; + } + + // Print out the line with the first columns + print "" . + ""; + + // If we need the date column, print it out + if ($using_date) { + print ""; + } + + // If we need the revision column, print it out + if ($using_rev) { + print ""; + } + + // End the line + print "\n"; + + // Collect files in WIP list + $wip_files[$finfo["name"]] = TRUE; + } + + print "
Work in progress filesTranslatorTypeDateCO-RevisionEN-Revision
$finfo[name]$finfo[person]$finfo[type]$finfo[date]$finfo[revision]" . + $missing_files[$finfo["name"]][1] . + "
\n

 

\n$navbar

 

\n"; + +} + +// Files translated, but without a revision comment +$count = count($missing_tags); +if ($count > 0) { + print "" . + "\n". + "". + "\n". + "\n"; + foreach($missing_tags as $val) { + // Shorten the filename (we have directory headers) + $short_file = basename($val[0]); + + // Guess the new directory from the full name of the file + $new_dir = dirname($val[0]); + + // If this is a new directory, put out dir headline + if ($new_dir != $prev_dir) { + + // Print out directory header + print "\n"; + + // Store the new actual directory + $prev_dir = $new_dir; + } + print "". + "\n"; + } + print "
Files without Revision-comment ($count files):Sizes in kB
en$LANGdiff
$new_dir
$short_file$val[1]$val[2]$val[3]
\n

 

\n$navbar

 

\n"; +} + +// Merge all work in progress files collected +$wip_files = array_merge( + $translation["files"], // Files for this translator + $translation["allfiles"] // Files for all the translators +); + +// Delete wip entires from available files list +foreach ($wip_files as $file) { + if (isset($missing_files[$file['name']])) { + unset($missing_files[$file['name']]); + } +} + +// Files not translated and not "wip" +$count = count($missing_files); +if ($count > 0) { + print "" . + "\n" . + "\n"; + foreach($missing_files as $file => $info) { + // Shorten the filename (we have directory headers) + $short_file = basename($file); + + // Guess the new directory from the full name of the file + $new_dir = dirname($file); + + // If this is a new directory, put out dir headline + if ($new_dir != $prev_dir) { + + // Print out directory header if not "." + print "\n"; + + // Store the new actual directory + $prev_dir = $new_dir; + } + + print "" . + "\n"; + } + print "
" . + " Available for translation ($count files):kB
$new_dir
$short_file$info[0]
\n

 

\n$navbar

 

\n"; + +} + +// All OK, end the file +print "\n\n"; + +?>