#!/usr/bin/tclsh
# Copyright (C) 2001-2023 Artifex Software, Inc.
# All Rights Reserved.
#
# This software is provided AS-IS with no warranty, either express or
# implied.
#
# This software is distributed under license and may not be copied,
# modified or distributed except as expressly authorized under the terms
# of the license contained in the file LICENSE in this distribution.
#
# Refer to licensing information at http://www.artifex.com or contact
# Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
# CA 94129, USA, for further information.
#
# Check various aspects of an about-to-be-released source fileset.
# Sets the following globals for use by files using this one:
# CHANGED(f) - defined as 1 for each f such that f~ or f.orig exists
# NEWSCHANGED(f) - defined as 1 for each f listed as changed in the
# NEWS* file
# NEWSDATE - the date in NEWSVERSION
# NEWSVERSION - the most recent Version line from the NEWS* file
# ---------------- Utilities ---------------- #
# Print an error message.
proc message {str} {
puts stderr "**** $str"
}
# Search for one or more occurrences of a pattern in a file.
# If any are found, set $linevar to the line containing the first occurrence,
# and return 1; otherwise, return 0.
proc grep1 {pattern file linevar} {
upvar $linevar line
set line ""
set cmd [list exec egrep $pattern $file]
catch "set line \[$cmd\]"
if {$line == ""} {return 0}
set line [lindex [split $line "\n"] 0]
return 1
}
# ---------------- Main program ---------------- #
# Identify the relevant NEWS file, setting NEWS.
set news {}
foreach f [glob -nocomplain NEWS* News*.htm doc/News*.htm] {
if {[regexp {^(doc/|)(NEWS([-_][A-Z0-9]*|)|News([-_][A-Za-z0-9]*|)\.htm)$} $f]} {lappend news $f}
}
if {[llength $news] != 1} {
if {$news == {}} {set news -nothing-}
puts "**** Looking for NEWS or News.htm, found: $news"
exit 1
}
set NEWS [lindex $news 0]
# Check the date and version number in the NEWS file.
# Set NEWSVERSION
if {![grep1 {^Version [0-9.]+[( ]} $NEWS vdate]} {
if {![grep1 {[<]/a>Version [0-9.]+[( ]} $NEWS vdate]} {
message "Unable to parse $NEWS!"
exit 1
}
}
regsub -all {<[^>]*>} $vdate "" vdate
puts "Most recent version in $NEWS: $vdate"
set vdmypat {^Version [0-9.]+(.*)\((([0-9x]+)/([0-9x]+)/([0-9x]+))\)$}
set vymdpat {^Version [0-9.]+(.*)\((([0-9x]+)-([0-9x]+)-([0-9x]+))\)$}
if [regexp $vdmypat $vdate skip skip2 rdate rmonth rday ryear] {
set dateformat %-m/%-d/%y
} elseif [regexp $vymdpat $vdate skip skip2 rdate ryear rmonth rday] {
set dateformat %Y-%m-%d
} else {
message "$NEWS release date is missing"
exit 1
}
if {![string match *x* $ryear]} {
if {$ryear >= 1900} {
} elseif {$ryear >= 50} {
set ryear [expr $ryear + 1900]
} else {
set ryear [expr $ryear + 2000]
}
}
set curdate [exec date +$dateformat]
if {$rdate != $curdate} {
message "Warning: current date is $curdate, release date is $rdate"
}
set NEWSVERSION $vdate
# Collect the list of changed files (those with a ~-file or .orig file,
# other than t and t.*).
proc changed_files {} {
set changed {}
foreach prefix {doc/ examples/ lib/ man/ src/ toolbin/ gnu/*/} {
foreach fx [glob -nocomplain ${prefix}*~ ${prefix}*.orig] {
if {[regexp {^(.*)(~|\.orig)$} $fx skip f]} {
lappend changed $f
}
}
}
return $changed
}
catch {unset CHANGED}
foreach f [changed_files] {set CHANGED($f) 1}
# Collect the list of files identified as changed in the current NEWS
# section.
proc news_changed_files {in} {
set changed {}
set para {}
set fnamepat {[-0-9A-Za-z_.*/]+}
set fn1pat "${fnamepat}( \\\[deleted\\\]| => $fnamepat|)"
set fnlistpat "${fn1pat}(,\[ \]*$fn1pat)*"
while {[gets $in l] >= 0 && ![regexp {(^|</a>)Version} $l]} {
set l [string trimright $l]
if {$l == "" || $l != [string trimleft $l]} {
# End of paragraph. Look for changed files in the previous one.
regsub {\) \*\*\*(.*)\*\*\*$} $para {)} para
if {[regexp "\\(($fnlistpat)\\)\$" $para skip files]} {
regsub -all {,} $files { } files
foreach f $files {
if {$f == {[deleted]}} {continue}
if {![regexp / $f]} {set f src/$f}
set fl [glob -nocomplain $f]
if {$fl != ""} {append changed " $fl"}
}
}
set para $l
} else {
append para " $l"
}
}
return $changed
}
catch {unset NEWSCHANGED}
set news [open $NEWS]
while {![regexp {(^|</a>)Version} [gets $news]]} { }
foreach f [news_changed_files $news] {set NEWSCHANGED($f) 1}
close $news
# Check that the files with ~- or .orig-files are 1-for-1 with files listed
# in the current NEWS section.
puts "[array size CHANGED] files with ~ or .orig,\
[array size NEWSCHANGED] changed in $NEWS."
# We'd like to handle gs_init.ps properly, but its embedded version number
# changes in every fileset. **** SPECIAL HACK FOR GS ****
foreach f "$NEWS lib/gs_init.ps src/version.mak" {catch {unset CHANGED($f)}}
foreach f {lib/gs_init.ps} {catch {unset NEWSCHANGED($f)}}
set c_n {}
foreach f [array names CHANGED] {if {![info exists NEWSCHANGED($f)]} {lappend c_n $f}}
set n_c {}
foreach f [array names NEWSCHANGED] {if {![info exists CHANGED($f)]} {lappend n_c $f}}
if {$c_n != ""} {puts "**** Changed, not in $NEWS: [lsort $c_n]"}
if {$n_c != ""} {puts "**** In $NEWS, not changed: [lsort $n_c]"}