Platon Technologies
not logged in Login Registration
EnglishSlovak
open source software development celebrating 10 years of open source development! Saturday, January 18, 2025

File: [Platon] / scripts / php / parsecvs / parsecvs.php (download)

Revision 1.27, Mon Feb 9 19:37:47 2009 UTC (15 years, 11 months ago) by nepto


Changes since 1.26: +3 -3 lines

Suppress array_merge() warnings

<?php

    // parsecvs.php - Platon SDG CVS commit reports prettyfier
    // Developed by Martin Karas <wolcano@pobox.sk>
    // Tag support by Ondrej Jombik <nepto@php.net> [11/1/2003]
    // Copyright (c) 2002-2003 Platon SDG, http://www.platon.sk/
    // Licensed under terms of GNU General Public License

    // $Platon: scripts/php/parsecvs/parsecvs.php,v 1.26 2005-02-07 22:38:46 rajo Exp $

    #
    # CONSTANTS
    #

    // Specify input/output streams (ie. files, sockets or std's)
    $input_file  = 'php://stdin';
    $output_file = 'php://stdout';

    // Made more liberal (20 compulsory dashes, others are arbitrary)
    // old: $begin_line = '----------------------------------------------';
    $begin_line = '--------------------[-]*';
    $msg_log_begin = '^Log Message:';
    $date_format = '^([A-Z][a-z]{2} *)?([A-Z][a-z]{2} *[0-9]+ *' .
            '[0-9]{2}:[0-9]{2}:[0-9]{2}) *CES?T *([0-9]{4})';
    $user_format = '^CVSUSER=([0-9a-zA-Z]*)';
    $directory_format = '^In directory';
    $project_name_format = '^Update of /home/cvs/(.*)';
    $cvsweblink_format = '^(http:[^     ]*)';
    $tag_oper_begin  = '^Tag operation: (.*)$';
    $tag_name_begin  = '^Tag name: (.*)$';
    $add_files_begin = '^Added Files:';
    $mod_files_begin = '^Modified Files:';
    $del_files_begin = '^Removed Files:';
    $in_file_list = "^(\t|        )";
    $project_head = '--[ Project %s ]--';
    $project_head_folding_char = '-';
    $sub_projects_separator = "----\n";
    $log_message_folding = '  ';
    
    #
    # FUNCTIONS
    #

    function my_array_walk($x)
    {
        // This will do array_unique() on third-level values of $x
        $ik = array_keys($x);
        for ($i = 0; $i < sizeof($ik); $i++) {
            $jk = array_keys($x[$ik[$i]]);
            for ($j = 0; $j < sizeof($jk); $j++)
                if (is_array($x[$ik[$i]][$jk[$j]])) {

                    /* To prevent merging [0] => array(), [1] => array(), ...
                       into one [0] => array().  Note that merging algorithm
                       in array_unique() is string-based, thus it saw
                       [0] => 'Array', [1] => 'Array', ... and it logically
                       merge it into one [0] => 'Array'. However, this is not
                       desirable for us.

                       -- Nepto [11/1/2003] */

                    $all_values_are_arrays = true;
                    foreach ($x[$ik[$i]][$jk[$j]] as $val) {
                        if (! is_array($val)) {
                            $all_values_are_arrays = false;
                            break;
                        }
                    }
                    // Skip merging process if all values are arrays
                    if (! $all_values_are_arrays) {
                        $x[$ik[$i]][$jk[$j]] = array_unique($x[$ik[$i]][$jk[$j]]);
                    }
                }
        }
        return $x;
    } // my_array_walk()

    function write_out_file_set($op = '*', $file_ar, $tags)
    {
        if (! is_array($file_ar) || count($file_ar) <= 0)
            return;

        $additional_file_infos = array();
        if (is_array($tags)) {
            foreach ($tags as $tag_ar) {
                foreach ($tag_ar['files'] as $file) {
                    $additional_file_infos[$file][] =
                        $tag_ar['operation'].' '.$tag_ar['name'];
                }
            }
        }

        global $out, $indent_str;
        $prefix = "$indent_str$op ";
        foreach ($file_ar as $filename) {
            fwrite($out, $prefix);
            if (is_array($additional_file_infos[$filename])) {
                for ($i = 0; $i < count($additional_file_infos[$filename]); $i++) {
                    if ($i == 0) {
                        $filename2 = str_pad($filename, 35, ' ', STR_PAD_RIGHT);
                    } else if ($i == 1) {
                        $filename2 = str_repeat(' ', 35 + strlen($prefix));
                    }
                    $add_info = $additional_file_infos[$filename][$i];
                    fwrite($out, "$filename2 $add_info\n");
                }
            } else {
                fwrite($out, "$filename\n");
            }
        }
    }

    #
    # MAIN JOB
    #

    $in = file($input_file);  // input split into array by lines
    $i  = 0;                  // starting line to parse
    $j  = -1;                 // current parsed report

    // Rewind to the beginning of the first commit. This will allow us
    // to parse commits with garbage texts on the top (ie. e-mails).
    for (; ! ereg($begin_line, $in[$i]); $i++);

    while ($i < sizeof($in)) {
        // BEGIN NEW COMMIT
        if (ereg($begin_line, $in[$i])) {
            // increasing report index
            $j++;
            // reseting all flags
            $in_msg_log   = false;
            $in_add_files = false;
            $in_mod_files = false;
            $in_del_files = false;
            // moving to the next line
            $i++;
            continue;
        }

        // LOG MESSAGE
        if (ereg($msg_log_begin, $in[$i])) {
            $in_msg_log = true;
            $i++;
            continue;
        }

        if ($in_msg_log) {
            if (ereg($begin_line, $in[$i])) {
                $in_msg_log = false;
                $i++;
                continue;
            }
            else {
                $reports[$j]['log_msg'][sizeof($reports[$j]['log_msg']) - 1] .=
                    rtrim($in[$i]);
                //$reports[$j]['log_msg'][0] .= rtrim($in[$i]) . "\n";
            }
        }

        // ADDED FILES
        if (ereg($add_files_begin, $in[$i])) {
            $in_add_files = true;
            $i++;
            continue;
        }
        
        if ($in_add_files) {
            if (!ereg($in_file_list, $in[$i])) {
                $in_add_files = false;
                continue;
            }

            $reports[$j]['added'] = 
                array_merge($reports[$j]['added'],
                    explode(' ', trim($in[$i])));
        }
        
        // MODIFIED FILES
        if (ereg($mod_files_begin, $in[$i])) {
            $in_mod_files = true;
            $i++;
            continue;
        }
        
        if ($in_mod_files) {
            if (!ereg($in_file_list, $in[$i])) {
                $in_mod_files = false;
                continue;
            }

            $reports[$j]['modified'] = 
                @array_merge($reports[$j]['modified'],
                explode(' ', trim($in[$i])));
        }

        // DELETED FILES
        if (ereg($del_files_begin, $in[$i])) {
            $in_del_files = true;
            $i++;
            continue;
        }
        
        if ($in_del_files) {
            if (!ereg($in_file_list, $in[$i])) {
                $in_del_files = false;
                continue;
            }

            $reports[$j]['deleted'] = 
                array_merge($reports[$j]['deleted'],
                    explode(' ', trim($in[$i])));
        }

        // DATE        //Accepted format: Mon May 20 18:06:09 CEST 2002
        if (ereg($date_format, $in[$i], $regs)) {
            $reports[$j]['date'][] = $regs[2] . ' ' . $regs[3];
        }

        // USERS
        if (ereg($user_format, $in[$i], $regs)) {
            $reports[$j]['users'][] = $regs[1];
        }

        // DIRECTORY
        if (ereg($directory_format, $in[$i])) {
            // This is redundant, simply ignoring it
        }

        // NAME
        if (ereg($project_name_format, $in[$i], $regs)) {
            // only project name
            $reports[$j]['name'] = trim(strtok($regs[1], '/'));
            $reports[$j]['directory'] = trim($regs[1]);
        }

        // CVSWEB link
        if (ereg($cvsweblink_format, $in[$i], $regs)) {
            // only URL
            $reports[$j]['cvsweblink'] = 
                @array_merge($reports[$j]['cvsweblink'], trim($regs[1]));
        }

        // TAG OPERATION
        if (ereg($tag_oper_begin, $in[$i], $regs)) {
            //$reports[$j]['tag_operation'][0] = trim($regs[1]);
            $reports[$j]['tag'][0]['operation'] = trim($regs[1]);
        }
        
        // TAG NAME
        if (ereg($tag_name_begin, $in[$i], $regs)) {
            //$reports[$j]['tag_name'][0] = trim($regs[1]);
            $reports[$j]['tag'][0]['name'] = trim($regs[1]);
        }

        $i++;
    }

    $merged = array();

    // Merge recursively all reports into one array
    // eg. join reports in same directory
    for ($i = 0; $i < sizeof($reports); $i++) {

        if (isset($reports[$i]['tag'][0]['name'])) {            
            $reports[$i]['tag'][0]['files'] = 
                (array) $reports[$i]['added'] +
                (array) $reports[$i]['modified'] +
                (array) $reports[$i]['deleted'];

            switch (@$reports[$i]['tag'][0]['operation']) {
                case 'add': $op = '+'; break;
                case 'del': $op = '-'; break;
                default:    $op = '?'; break;
            }
            $reports[$i]['tag'][0]['operation'] = $op;
        }
        unset($a);
        $a[$reports[$i]['directory']] = $reports[$i];
        $merged = array_merge_recursive($merged, $a);
    }
    unset($i);
    unset($a);

    $merged_unique = my_array_walk($merged);
    ksort($merged_unique);

    // DEBUG
    //var_dump($reports);
    //var_dump($merged);
    //var_dump($merged_unique);

    unset($reports);
    unset($merged);

    $out  = fopen($output_file, 'w');
    $keys = array_keys($merged_unique);
    $i    = 0;
    $name = '';

    // OUTPUT:
    // Print out the merged/unique to $out

    while ($i < sizeof($merged_unique)) {
        $k = $keys[$i];
        $m = $merged_unique[$k];
        $new_name = is_array($m['name']) ? join(', ', $m['name']) : $m['name'];
        
        if (strcmp($new_name, $name)) {
            // Print new project name
            fwrite($out, sprintf($project_head, $new_name));
            ;
            fwrite($out, str_repeat($project_head_folding_char, 70 - strlen($new_name) - 16));
            fwrite($out, "\n");
            $name = $new_name;
        }
        else {
            // Separate subdirectories of the same project
            fwrite($out, $sub_projects_separator);
        }

        // DIRECTORY
        fwrite($out, 'Path:  ');
        fwrite($out, is_array($m['directory'])
            ? join(', ', $m['directory'])
            : $m['directory']);
        fwrite($out, "/\n");

        // DATE
        if (is_array($m['date'])) {
            fwrite($out, 'Date:  ' . $m['date'][sizeof($m['date']) - 1]);
            fwrite($out, "\n");
        }

        // EDITORS
        if (is_array($m['users'])) {
            /* there is no fprintf() in PHP,
               so we must use fwrite()/sprintf() combo */
            fwrite($out, sprintf('User%s ',
                        count($m['users']) == 1 ? ': ' : 's:'));
            fwrite($out, implode(', ', $m['users']) . "\n");
        }

        // MODIFIED FILES
        if (is_array($m['added']) || is_array($m['modified']) ||
            is_array($m['deleted'])) {
            if ((count($m['added']) + count($m['modified']) +
                count($m['deleted'])) > 1)
                fwrite($out, "Files:\n");
            else
                fwrite($out, "File:\n");
        }
            
        // mod = mod - add
        if (is_array($m['added']) && is_array($m['modified'])) {
            $m['modified'] = array_diff($m['modified'], $m['added']);
        }
        
        // $indent_str is used as global in write_out_file_set()
        $indent_str = str_repeat(' ', strlen('Files') + 2);

        write_out_file_set('+', $m['added'],    $m['tag']);
        write_out_file_set('*', $m['modified'], $m['tag']);
        write_out_file_set('-', $m['deleted'],  $m['tag']);

        // LOG MESSAGES
        if (is_array($m['log_msg'])) {
            fwrite($out, "Message:\n");
            for ($l = 0; $l < count($m['log_msg']); $l++) {
                if (trim($m['log_msg'][$l]) == '')
                    unset($m['log_msg'][$l]);
            }

            fwrite($out, $log_message_folding .
                implode("\n$log_message_folding",
                //str_replace("\n", "\n$log_message_folding", $m['log_msg'])
                $m['log_msg']
            ) . "\n");
        }

        // LOG MESSAGES
        if (is_array($m['cvsweblink'])) {
            fwrite($out, "CVSweb URL:\n");

            fwrite($out, $log_message_folding .
                implode("\n$log_message_folding",
                $m['cvsweblink']
            ) . "\n");
        }

        $i++;
    }
    
    fflush($out);
?>

Platon Group <platon@platon.org> http://platon.org/
Copyright © 2002-2006 Platon Group
Site powered by Metafox CMS
Go to Top