Updated 2003-03-18 13:55:08

Format CVS or RCS log entries into ChangeLog format.

This code is an application, probably similar to a Perl thing at [1], but obviously superior, because it is written in Tcl.

NEM 4Feb2003 - I can't seem to get this to work. It just hangs reading the log from stdin. Any ideas? The command I used was:
 cvs log | tclsh log2changelog

Is that correct?

TR - the problem is: 'cvs log' also outputs lines containing '=' characters. So changing the 'string match' line to a suited regexp, will fix the problem of an infinite loop under certain conditions.
    #!/bin/sh
    # restart using tclsh \
    exec tclsh "$0" "$@"

    #------------------------------------------------------
    #
    #  log2changelog.tcl
    #
    #  Create changelog entries from cvs or rcs log listing
    #
    #  Read an rcs/rlog or cvs/log listing, and remap the log
    #  entries into a format like:
    #
    #    2002/07/02 Author
    #       * file1.tcl:
    #       * file2.tcl:
    #       Changed contents of files.
    #
    #
    #  Use Tcl arrays to re-map the data into entries per date,
    #  developer, and comment string.  Group date/author
    #  changes together.  Match multiple files with identical
    #  comments.  Reformat comment text.
    #
    #------------------------------------------------------

    #  Read rcs/cvs log data from standard input
    while { ! [eof stdin] } {
	lappend data [gets stdin]
    }

    #  Load several arrays with the log entries
    for {set i 0} {$i<[llength $data]} {incr i} {

	set line [lindex $data $i]
	switch -glob -- $line {

	    "*Working file:*" {
		regexp {Working file: (.*)} $line -> filename
	    }

	    "date:*" {
		scan $line "date: %s %s author: %s" date time author
		set author [string trim $author ";"]

		# read the comment lines following date
		set comment ""
		incr i
		set line [lindex $data $i]
                # [TR]: use regexp here to see if log ends:
                while { ! [regexp "(-----*)|(=====*)" $line] } {
		    append comment $line "\n"
		    incr i
		    set line [lindex $data $i]
		}

		#  Store this date/author/comment
		lappend entries [list $date $author]
		lappend comments($date,$author) $comment
		lappend files($date,$author,$comment) $filename

	    }
	}
    }

    #  Now that we've loaded the data into some
    #  arrays, let's print out the changelog

    foreach e [lsort -unique -decreasing $entries] {

	#  print the date/author
	foreach {date author} $e {break}
	puts "$date $author"
	puts ""

	#  Find all the comments submitted this date/author
	foreach c [lsort -unique $comments($date,$author)] {

	    set txt ""
	    #  Print all files for a given comment
	    foreach f [lsort -unique $files($date,$author,$c)] {
		puts "\t* $f:"
	    }

	    #  Format and print the comment
	    #  (note that we saved the newlines, just in case
	    #   somebody wants to print the comment without
	    #   reformatting.)
	    set c [string map {"\n" " "} $c]
	    set len 60
	    while { [string length $c] > 0 } {
		set brk [string last " " $c $len]
		if { $brk < 0 } {set brk $len}
		puts "\t[string range $c 0 $brk]"
		set c [string range $c [expr {$brk+1}] end]
	    }
	    puts ""
	}
    }

Category Application