###############################################################################
#
# sourceTag.eagle -- Source Version Tag Tool
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################
package require Eagle
proc usage { error } {
if {[string length $error] > 0} then {puts stdout $error}
puts stdout "usage:\
[file tail [info nameofexecutable]]\
[file tail [info script]] <SourceIdMode> <fileName>"
#
# NOTE: Indicate to the caller, if any, that we have failed.
#
exit 1
}
set modes [list \"SourceIdMode\"]
set argc [llength $argv]
if {$argc == 2} then {
#
# NOTE: Are we updating the "PatchLevel.cs" file?
#
set mode [lindex $argv 0]
if {[string length $mode] > 0} then {
#
# NOTE: Get the file name to read/update/write.
#
set fileName [lindex $argv 1]
#
# NOTE: Make sure the file name provided is not obviously
# invalid.
#
if {[string length $fileName] > 0} then {
#
# NOTE: Read all the data out of the text file.
#
set data [readFile $fileName]
#
# NOTE: Normalize to Unix line-endings.
#
set data [string map [list \r\n \n] $data]; # Unix.
#
# NOTE: Figure out what mode we are in.
#
switch -exact -nocase -- $mode {
SourceIdMode {
#
# NOTE: Query the source identifier from Fossil, if available.
# If we are not within an active checkout, this will fail.
#
set pattern {^checkout:\s+([^\s]+)\s+(.*)\s+$}
if {[catch {set exec [exec -success Success -directory \
[file dirname $fileName] -- fossil info]}] || \
[regexp -line -- $pattern $exec dummy id timeStamp] == 0} then {
#
# NOTE: We could not query the source identifier(s); therefore,
# use obviously invalid ones. We would also be able to
# use null values here except that these values end up in
# native C header files as well (i.e. not just managed
# assembly attribute values).
#
set id 0000000000000000000000000000000000000000
set timeStamp "0000-00-00 00:00:00 UTC"
}
#
# NOTE: Match against this pattern in the "PatchLevel.cs"
# file (this pattern is fairly strict to prevent
# false-positives).
#
set pattern1 {AssemblySourceId\(.*?\)}
set pattern2 {AssemblySourceTimeStamp\(.*?\)}
set pattern3 {INTEROP_SOURCE_ID\s+".*?"}
set pattern4 {INTEROP_SOURCE_TIMESTAMP\s+".*?"}
#
# NOTE: Build the final replacement specification string.
#
set subSpec1 [appendArgs AssemblySourceId(\" $id \" )]
set subSpec2 [appendArgs AssemblySourceTimeStamp(\" $timeStamp \" )]
set subSpec3 [appendArgs INTEROP_SOURCE_ID " \"" $id \"]
set subSpec4 [appendArgs INTEROP_SOURCE_TIMESTAMP " \"" $timeStamp \"]
#
# NOTE: Perform the replacements in the original data
# (first match only).
#
set count 0
incr count [regsub -nocase -- $pattern1 $data $subSpec1 data]
incr count [regsub -nocase -- $pattern2 $data $subSpec2 data]
incr count [regsub -nocase -- $pattern3 $data $subSpec3 data]
incr count [regsub -nocase -- $pattern4 $data $subSpec4 data]
#
# NOTE: If we actually replaced anything, we need to write back
# to the original file; otherwise, leave it alone.
#
if {$count > 0} then {
#
# NOTE: Show how we tagged it.
#
puts stdout [appendArgs "tagged \"" $fileName "\" " $mode \
" " $id " " $timeStamp]
#
# NOTE: Re-write the original file with the modified data.
#
writeFile $fileName [string map [list \n \r\n] $data]; # DOS.
} else {
#
# NOTE: We could not replace the string. This is considered
# an overall failure.
#
usage [appendArgs "pattern \"" $pattern "\" not found in \"" \
$fileName \"]
}
}
default {
usage [appendArgs "unknown mode, must be " [join $modes " "]]
}
}
} else {
usage "invalid file name"
}
} else {
usage [appendArgs "invalid mode, must be " [join $modes " "]]
}
} else {
usage ""
}