Mark Derricutt <[EMAIL PROTECTED]> wrote: >On Mon, 10 Apr 2000, Ronald Henderson wrote: > >> http://www.red-bean.com/~kfogel/cvs2cl.shtml > >I was wondering if there's a ChangeLog script available that works under >NT/95 against a pserver? > >Mark Mark, Here's one I wrote for WinCVS. It isn't as complete as cvs2cl.pl, but like everything, it'll grow over time. -- * David Gravereaux * Tomahawk Software Group If knowlege is power, how come the more I learn, the more I realize how much I don't know? That isn't very empowering.
#!CVSGUI1.0 --selection --name "Build ChangeLog" # this will be a WinCVS macro for generating a ChangeLog # It isn't finished at this time. A work in progress... # # Please send diffs to David Gravereaux <[EMAIL PROTECTED]> # if you can improve this :) # # RCS: @(#) $Id: cvs2cl.tcl,v 1.4 2000/03/06 02:32:45 davygrvy Exp $ namespace eval ::Cvs2CL { variable db ;# our database array array set db [list] variable usermap ;# user translations from $CVSROOT/CVSROOT/users array set usermap [list] variable outputList [list] ;# the "structure" we write output from variable sorter [list] ;# the pre-sort helper list variable CLog_fname "ChangeLog" ;# the output filename we want to use variable rawLog ;# All the log in one string before parsing variable major [lindex [split $::tcl_version .] 0] variable minor [lindex [split $::tcl_version .] 1] } proc ::Cvs2CL::Init {} { variable CLog_fname variable rawLog variable usermap if {[regexp {^(.*)wincvs.exe$} [info nameofexecutable]]} { set cvsCmd [list cvs -Q log] # uncomment this stuff when the replace works in [Cvs2CL::ReWriteIt] # #if {![catch {set fOldLog [open $CLog_fname r]}]} { # cvsout "Checking date range of current $CLog_fname...\n" # # the first "word" of the first line is a date string. # # we ask cvs for logs greater than this old date # lappend cvsCmd -d "[join [split [lindex [split [gets $fOldLog] { }] 0] /] -]>" # close $fOldLog #} cvsout "Downloading the log...\n" set rawLog [eval $cvsCmd] # TODO: fill the usermap array here } else { # debugging under tclsh82 puts "Checking date range..." set cvsCmd [list cvs -Q log] #if {![catch {set fOldLog [open $CLog_fname r]}]} { # # the first "word" of the first line is a date string. # lappend cvsCmd -d "[lindex [split [gets $fOldLog] { }] 0]>" # close $fOldLog #} #puts $cvsCmd set flog [open c:/dev/logItcl.txt r] fconfigure $flog -encoding ascii -translation auto # bring the file into Tcl in one big SLAM! # this of-course assumes one character==one byte seek $flog 0 end set theEnd [tell $flog] seek $flog 0 start fconfigure $flog -buffersize $theEnd puts "Downloading the log..." set rawLog [read $flog $theEnd] close $flog proc ::cvsout {text} {puts -nonewline $text} } } proc ::Cvs2CL::cmpTime {a b} { variable major variable minor if {$major <= 8 && $minor < 3} { # ISO8601 date formats can't be scanned by tcl8.2, bummer... # works in 8.3, though... # # clock scan wants mm/dd/yyyy, so convert it from yyyy-mm-dd. # set al [split $a -] set a [lreplace $a 0 0 [list "[lindex $al 1]/[lindex $al 2]/[lindex $al 0]"]] set bl [split $b -] set b [lreplace $b 0 0 [list "[lindex $bl 1]/[lindex $bl 2]/[lindex $bl 0]"]] } return [expr {[clock scan $a -gmt 1] - [clock scan $b -gmt 1]}] } proc ::Cvs2CL::cmpTI {a b} { if {[set sort [cmpTime [lindex $a 0] [lindex $b 0]]] == 0} { return [expr {[lindex $b 1] - [lindex $b 1]}] } return $sort } proc ::Cvs2CL::cmpDA {a b} { set dateA [lindex [split $a ,] 0] set dateB [lindex [split $b ,] 0] return [cmpTime $dateA $dateB] } proc ::Cvs2CL::cmpInt {a b} { return [expr {$a - $b}] } proc ::Cvs2CL::ParseIt {} { variable db variable sorter variable rawLog variable CLog_fname array set db {} set sorter {} set id 0 # make each line a list element set rawLogList [split $rawLog \n] # count the number of lines set lines [llength $rawLogList] for {set a 0} {$a < $lines} {incr a} { set line [lindex $rawLogList $a] # The log for a certain file and version starts with # Working file: <filename> # The is our tag for a new entry into our database. First we just # store <filename> in fname if {[regexp {^Working file: ([^,]+)} $line null fname]} { # we don't care about ourselves if {![string compare $CLog_fname $fname]} { # skip all the way forward to the next while {$a < $lines} { if {[regexp {^======} [lindex $rawLogList $a]]} {break} {incr a} } } continue } # A line like # date: <date> <time> ... # follows soon. Everthing after that up to a line with all `='s in # it is stored. if {[regexp {^date:} $line]} { set date [join [split [lindex $line 1] /] -] set author [string trimright [lindex $line 4] {;}] set text {} # ignore branches if {[regexp {^branches:} [lindex $rawLogList [expr {$a+1}]]]} { incr a } # extract the message while {[incr a] < $lines} { set line [lindex $rawLogList $a] if {[regexp {^------} $line] || [regexp {^======} $line]} break append text "$line\n" } set text [string trimright $text \n] if {![string compare $text "Initial revision"]} { # we don't log the initial import branch announcement continue } if {![string compare $text "no message"]} { # no message means exactly that. So ignore it. continue } set db($id,fname) $fname set db($id,date) $date set db($id,text) $text set db($id,author) $author lappend sorter [list $date $id] incr id } } } proc ::Cvs2CL::SortIt {} { variable outputList variable sorter variable db array set dates [list] array set datesAuthors [list] # first, do a rough sort along date set preSort [lsort -command cmpTI -decreasing $sorter] # next, we seperate it by date. foreach element $preSort { lappend dates([lindex $element 0]) [lindex $element 1] } # next, sub-divide each date by the commit author foreach date [array names dates] { # sort the id's in decending numerical order set dates($date) [lsort -command cmpInt -decreasing $dates($date)] foreach id $dates($date) { lappend datesAuthors($date,$db($id,author)) $id } } # foreach author on a specific date, organize by log message and build the # applies-to list then store it, repeat 'till done. foreach DApair [lsort -command cmpDA -decreasing [array names datesAuthors]] { if {[array exist commitArray]} {unset commitArray} set entry [list] lappend entry $db([lindex $datesAuthors($DApair) 0],date) lappend entry $db([lindex $datesAuthors($DApair) 0],author) foreach id $datesAuthors($DApair) { lappend commitArray($db($id,text)) $db($id,fname) } # alphabetize 'em foreach commitMsg [array names commitArray] { set commitArray($commitMsg) [lsort $commitArray($commitMsg)] } lappend entry [array get commitArray] lappend outputList $entry } } proc ::Cvs2CL::RewriteIt {} { variable usermap variable outputList variable CLog_fname # if {[file exist $CLog_fname]} { # file rename $CLog_fname $CLog_fname.old # } set fCLog [open $CLog_fname w] foreach outputElement $outputList { # write the date puts -nonewline $fCLog "[lindex $outputElement 0] " # write the author of this commit. translate to an email, if listed # in the usermap array we got from CVSROOT/users if {[info exist usermap([lindex $outputElement 1])]} { puts $fCLog $usermap([lindex $outputElement 1]) } else { puts $fCLog [lindex $outputElement 1] } if {[array exist commits]} {unset commits} array set commits [lindex $outputElement 2] foreach msg [array names commits] { # write the applies-to files foreach applyto $commits($msg) { puts $fCLog "\t* $applyto:" } # TODO: make this wordwrap to look all nice and stuff puts $fCLog \t\t$msg\n } } close $fCLog # if {[file exist $CLog_fname.old]} { # file delete -force $CLog_fname.old # } } Cvs2CL::Init cvsout "Parsing output...\n" Cvs2CL::ParseIt cvsout "Sorting entries...\n" Cvs2CL::SortIt cvsout "Rewriting ChangeLog...\n" Cvs2CL::RewriteIt cvsout "Done!\n"