Skip to content

Commit

Permalink
Unify changelog generation.
Browse files Browse the repository at this point in the history
(cherry picked from commit 4b9c30a)
  • Loading branch information
thommey authored and vanosg committed Mar 26, 2017
1 parent b4a472c commit 0abd960
Show file tree
Hide file tree
Showing 2 changed files with 261 additions and 85 deletions.
54 changes: 0 additions & 54 deletions misc/genChangelog

This file was deleted.

292 changes: 261 additions & 31 deletions misc/genchanges
@@ -1,6 +1,6 @@
#! /usr/bin/env tclsh
#
# genchanges - Generate changes summary for doc/Changes files.
# genchanges - Generate changelog (doc/Changes and ChangeLog) files.
#
# Copyright (C) 2017 Eggheads Development Team
#
Expand All @@ -22,48 +22,278 @@
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
package require Tcl 8.5

proc show_usage {} {
puts "Syntax: $::argv0 <show changes since this git tag (e.g. v1.8.0)> \[show changes to this git tag (e.g. v1.8.1)\]"
puts "normal usage: \"$::argv0 v1.8.0\", then paste the result into doc/Changes1.8"
exit 1
package require Tcl 8.6
package require textutil::adjust

proc get_usage {} {
return [subst [join {
{Syntax: $::argv0 \[options\] <command>} {} {Commands:}
{short - Generate short changelog (doc/ChangesX.Y)}
{full - Generate full changelog (ChangeLog)}
{release - OVERWRITE ChangeLog and doc/ChangesX.Y}
{} {Options (general):}
{-d - Verbose debug logging}
{-r <remote> - Specify remote for tags and public branches}
{} {Options (short):}
{-e <version> - Specify ref to exclude with ancestors}
{-i <version> - Specify ref to include with ancestors}
{-n <version> - Specify the upcoming version}
{} {Examples:}
{ Generate doc/Changes1.8 for v1.8.2rc3:}
{ $::argv0 -e v1.6.21 -i v1.8.1 -i v1.8.2 -i stable/1.8 -n 1.8.2rc3 short}
{ Generate doc/Changes1.8 for v1.8.3 final (make sure version order is correct at the end):}
{ $::argv0 -e v1.6.21 -i "v1.8.*" -i stable/1.8 -n 1.8.3 short}
{ Generate ChangeLog for v1.8.3 final:}
{ $::argv0 -i stable/1.8}
} \n]]
}

if {[llength $argv] != 1 || [set basecommit [lindex $argv 0]] in {-h --help}} {
show_usage
proc commands {} {
lmap cmd [info commands cmd:*] {
string range $cmd 4 end
}
}

if {[catch {exec git rev-list $basecommit..HEAD} commits]} {
puts "Error: git rev-list $basecommit..HEAD returned\n$commits\n"
proc fatal {msg {showusage 0}} {
if {$msg ne ""} {
puts stderr $msg
if {$showusage} {
puts stderr ""
}
}
if {$showusage} {
puts stderr [get_usage]
}
exit 1
}

set result ""
foreach commit [lreverse $commits] {
set fullmsg [exec git show -s --pretty=format:%B $commit]
set shortmsg [exec git show -s --pretty=format:%s $commit]
set date [clock format [exec git show -s --pretty=format:%ct $commit] -gmt 1 -format "%Y-%m-%d"]
set found ""
set patch ""
foreach {- category names} [regexp -nocase -all -inline -- {(found|patch) by:([^\r\n/]+)} $fullmsg] {
foreach nick [split $names {, }] {
set nick [string trim $nick ""]
if {$nick ne ""} {
dict set [string tolower $category] $nick 1
proc pop {listVar} {
upvar 1 $listVar list
set e [lindex $list 0]
set list [lrange $list 1 end]
return $e
}

proc log {text} {
puts stderr $text
}

proc vlog {text} {
if {$::verbose} {
log $text
}
}

proc parsecmdline {argv} {
global verbose
if {![llength $argv]} {
fatal "" 1
}
foreach var {remote command version includes excludes} {
set $var ""
}
set verbose 0
while {[llength $argv]} {
set arg [pop argv]
if {[string index $arg 0] eq "-"} {
for {set i 1} {$i < [string length $arg]} {incr i} {
set c [string index $arg $i]
switch -exact -- $c {
"r" { set remote [pop argv] }
"d" { set verbose 1 }
"v" { set version [pop argv] }
"i" { lappend includes [pop argv] }
"e" { lappend excludes [pop argv] }
default {
fatal "Unknown option: -$c" 1
}
}
vlog "OptParse: $c (left: $argv)"
}
} else {
set command $arg
break
}
}
set secondline ""
if {[dict size $found]} {
lappend secondline "Found by: [join [dict keys $found] {, }]"
if {$command eq ""} {
fatal "No command specified." 1
show_usage
}
if {[dict size $patch]} {
lappend secondline "Patch by: [join [dict keys $patch] {, }]"
if {![llength $includes]} {
fatal "No -i includes specified." 1
}
if {[llength $secondline]} {
append shortmsg "\n [string repeat " " 10] [join $secondline { / }]"
foreach var {remote version includes excludes} {
cfg$var [set $var]
}
lappend result " $date $shortmsg"
return $command
}
puts [join [lreverse $result] \n\n]

interp alias {} cfgincludes {} cfgtags includes
interp alias {} cfgexcludes {} cfgtags excludes

proc cfgtags {varName patterns} {
global remote
upvar #0 $varName tags
set tags ""
foreach pattern $patterns {
set tmp [regexp -all -inline -- {\S+} [exec git tag -l $pattern]]
if {![llength $tmp]} {
# no matching tags
if {[catch {exec git rev-parse --verify -q $remote/$pattern}]} {
fatal "Could not parse revision $pattern on remote $remote."
}
set tmp [list $remote/$pattern]
}
lappend tags {*}$tmp
}
}

proc cfgversion {version} {
if {$version ne "" && ![regexp {^\d+\.\d+\.\d+} $version]} {
fatal "Invalid ersion number: $version. Try 1.8.1 or similar."
}
set ::version $version
}

proc cfgremote {remote} {
set remotes [regexp -all -inline -- {\S+} [exec git remote]]
if {![llength $remotes]} {
fatal "No git remotes configured."
exit 1
}
if {$remote eq ""} {
if {[llength $remotes] == 1} {
set remote [lindex $remotes 0]
} else {
fatal "Multiple remotes available, must specify -r. Available: [join $remotes {, }]"
}
}
if {[llength $remotes] == 1 && $remote eq ""} {
set remote [lindex $remotes 0]
}
if {$remote ni $remotes} {
fatal "Unknown remote: $remote. Available: [join $remotes {, }]"
exit 1
}
vlog "Remotes: '[join $remotes ',']'. Using '$remote'"
set ::remote $remote
}

proc start {} {
global remote
set command [parsecmdline $::argv]
if {$command ni [commands]} {
fatal "Unknown command: $command. Available: [join [commands] {, }]" 1
}
log "Working with remote $remote..."
cmd:$command
}

proc revlist {} {
global includes excludes
set includestr $includes
set excludestr [lmap x $excludes { return -level 0 ^$x }]
return [list {*}$includestr {*}$excludestr]
}

proc doexec {cmd} {
log "Executing: [join $cmd]"
if {[catch {exec {*}$cmd} res]} {
fatal "Error during executing: $res"
}
set res [regsub -all -- {\n\n\n+} [string trim $res] "\n\n"]
log "Executed: [join $cmd]"
return $res
}

proc cmd:full {} {
set revlist [revlist]
set cmd [list git log --no-merges --date-order --name-status {--pretty=format:%n------------------------------%nCommit %h (%ai) by %aN %n%n%B%n%n} {*}[revlist]]
puts [doexec $cmd]
}

proc cmd:short {} {
global version includes excludes
if {$version eq ""} {
fatal "Need version number (-v) for short changelog."
}
set cmd [list git rev-list --no-merges --reverse --author-date-order {*}[revlist]]
set commits [doexec $cmd]
set taglist [regexp -all -inline -- {\S+} [exec git tag --list]]
set tags ""
foreach tag $taglist {
dict set tags [string trim [exec git rev-parse $tag]] $tag
}
set lastdate ""
set lastappend ""
foreach commit $commits {
set fullmsg [exec git show -s --pretty=format:%B $commit]
set shortmsg [exec git show -s --pretty=format:%s $commit]
set date [clock format [exec git show -s --pretty=format:%ct $commit] -gmt 1 -format "%Y-%m-%d"]
set found ""
set patch ""
set shortmsg [string trim $shortmsg "- "]
if {$lastappend ne ""} {
lappend result {*}[string map [list %%CHANGELOGDATE%% [expr {($date eq $lastdate && !$forcedate) ? "[string repeat " " 10]" : "$lastdate"}]] $lastappend]
}
set forcedate 0
foreach {- category names} [regexp -nocase -all -inline -- {(found|patch) by:([^\r\n/]+)} $fullmsg] {
foreach nick [split $names {, }] {
set nick [string trim $nick ""]
if {$nick ne ""} {
dict set [string tolower $category] $nick 1
}
}
}
set shortmsgs ""
#ugly specific fixup
if {[string index $shortmsg 0] eq "*"} {
set split [split $shortmsg *]
foreach e $split {
set e [string trim $e]
if {$e eq ""} { continue }
lappend shortmsgs $e
}
} else {
set shortmsgs [list $shortmsg]
}
set secondline ""
if {[dict size $found]} {
lappend secondline "Found by: [join [dict keys $found] {, }]"
}
if {[dict size $patch]} {
lappend secondline "Patch by: [join [dict keys $patch] {, }]"
}
if {[llength $secondline]} {
set lastmsg [lindex $shortmsgs end]
append lastmsg "\n [string repeat " " 12] [join $secondline { / }]"
set shortmsgs [list {*}[lrange $shortmsgs 0 end-1] $lastmsg]
}
set lastappend ""
set lastmsg [lindex $shortmsgs end]
set shortmsgs [lrange $shortmsgs 0 end-1]
foreach shortmsg $shortmsgs {
set lines [split [textutil::adjust::adjust $shortmsg -full true -justify left -length 120 -strictlength true] \n]
lappend lastappend " [string repeat " " 10] * [pop lines]"
foreach line $lines {
lappend lastappend " [string repeat " " 12] $line"
}
}
set lines [split [textutil::adjust::adjust $shortmsg -full true -justify left -length 120 -strictlength true] \n]
lappend lastappend " %%CHANGELOGDATE%% * [pop lines]"
foreach line $lines {
lappend lastappend " [string repeat " " 10] * $line"
}
if {[dict exists $tags $commit]} {
lappend lastappend "\nEggdrop [dict get $tags $commit] (released $date):\n"
set forcedate 1
}
set lastdate $date
}
lappend result {*}[string map [list %%CHANGELOGDATE%% $lastdate] $lastappend]
puts "Eggdrop Changes (Last Updated [clock format [clock seconds] -gmt 1 -format "%Y-%m-%d"]):\n__________________________________________\n\nEggdrop v$version:\n"
puts [join [lreverse $result] \n]
}

start

0 comments on commit 0abd960

Please sign in to comment.