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"

Reply via email to