#!/bin/sh # # aegis - project change supervisor # Copyright (C) 2005, 2006, 2008 Peter Miller # Copyright (C) 1998-2004 Endocardial Solutions, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see # . # # Must deal with various locations of wish on different systems so # the next line restarts using wish from path \ exec wish "$0" -- ${1+"$@"} # # aexver - script to easily view (historical) versions of aegis files. # # pops a listbox with all (project) filenames in it. # when user double-clicks on a file, another box comes up # listing all the revisions of that file. # selecting any two revisions will bring up a diff comparing # those revisions to each other. # set Pid [exec /bin/sh -c "echo \$$"] set TmpFile "/tmp/aexver.$Pid"; set RevSort byBranch set VersReport File_Version_History # Process arguments to get project name set state flag foreach arg $argv { switch -- $state { flag { switch -glob -- $arg { -p* { set state project } default { puts stderr "unknow option $arg" } } } project { set ProjName $arg set state flag } } } # If arguments did not supply the project name # then try to get project name from AEGIS_PROJECT environment if { ! [info exists ProjName] } { if [info exists env(AEGIS_PROJECT)] { set ProjName $env(AEGIS_PROJECT) } else { if [ catch {exec aesub -bl {$project}} ProjName ] { puts stderr $ProjName exit 1 } } } # We also need the project trunk name if [ catch {exec aesub -bl -p $ProjName {${project trunk_name}}} ProjTrunk ] { puts stderr $ProjTrunk exit 1 } # See if user has AE2DIFF set - if not help em out # use that set in user AEDIFF. # unless unset - then default to xdiff if { ! [info exists env(AE2DIFF)] } { if [info exists env(AEDIFF)] { set env(AE2DIFF) $env(AEDIFF) } else { set env(AE2DIFF) xdiff } } # A list for each file in the project variable FileList set SubDir {} listbox .list -yscroll ".scroll set" -relief raised \ -width 45 -height 30 -font {Courier 14} frame .sort pack .sort -side top label .sort.msg -text "sort by: " pack .sort.msg -side left radiobutton .sort.b -variable RevSort \ -text Branch -value byBranch pack .sort.b -side left radiobutton .sort.r -variable RevSort \ -text Revision -value byRevision pack .sort.r -side left pack .list -side left scrollbar .scroll -command ".list yview" pack .scroll -side right -fill y proc loadmainwin {dir} { global FileList SubDir # clear existing list if any .list delete 0 end if { [string compare $dir .] == 0} { wm title . "top" set pat * set field 0 set SubDir {} } else { # if too long munge to ...{part} later wm title . $dir set SubDir $dir set pat "$dir/*" set field [llength [file split $dir]] # allow for upward movement .list insert end ".." } foreach f [array names FileList $pat] { set name [lindex [file split $f] $field] set display($name) 1 } foreach f [lsort -ascii [array names display]] { .list insert end $f } } # Sort methods proc byRevision {a b} { # revision is first field # split into major and minor parts set ar [split [lindex [split $a { }] 0] .] set br [split [lindex [split $b { }] 0] .] set amaj [lindex $ar 0] set amin [lindex $ar 1] set bmaj [lindex $br 0] set bmin [lindex $br 1] # first compare major revs set r [expr $bmaj - $amaj] # if equal then compare minor revs if { $r == 0 } { set r [expr $bmin - $amin] } return $r } # byBranch is easy - just leave order alone proc byBranch {a b} { return 0 } # method to turn a proj:chg and delta number into a delta form argument # dws.1.6:232 45 --> -c 1.6.D045 # dws:43 --> -c 43 proc chgArg {pr delta} { # split dws.1.6:232 into dws.1.6 and 232 set prch [split $pr :] # take dws. off the pr part regsub {[^.]+.} [lindex $prch 0] {} branch # if any branch part left if { [string length $branch] > 0 } { set ret [format {-c %s.D%03d} $branch $delta] } else { set ret [format {-c %d} [lindex $prch 1]] } return $ret } # Put the window on the screen and show something # before users think the program is hung wm title . "Loading" .list insert end {Loading Project Files ...} update # Now get the project file list - which might take a while if [catch {open "|aegis -l pf -ter -p $ProjName" r} pfd ] { puts stderr $pfd exit 1 } # Create an array where the names are the filenames # and values will be filled in with the version list foreach f [split [read $pfd] \n] { if { [string length $f] > 0 } { set FileList($f) {} } } # start at the top loadmainwin {.} bind .list { global FileList SubDir VersReport set select [selection get] # puts stderr "selected:$select" if { [string length $SubDir] > 0 } { set name [file join $SubDir $select]; } else { set name $select } # first check for the .. symbol to go up a level if { [string compare $select {..}] == 0 } { # going up - trim one level off SubDir set SubDir [file dirname $SubDir] # puts stderr "selected up load:$SubDir" loadmainwin $SubDir } elseif { ! [info exists FileList($name) ] } { # Not in the list - must be a directory # puts stderr "selected dir load:$name" loadmainwin $name } else { # they selected a file so prepare the revision list if { [winfo exists .d] } { # already there - just clean it out .d.lbox delete 0 end # and make sure it is not hidden raise .d } else { # make up the new widget toplevel .d frame .d.ctrls pack .d.ctrls -side bottom -fill x -pady 2m label .d.ctrls.msg -wraplength 1.5i -justify left \ -text "select any two versions" button .d.ctrls.go -text "Go" pack .d.ctrls.msg .d.ctrls.go -side left -expand 1 listbox .d.lbox -selectmode multiple -yscroll ".d.scroll set" \ -relief raised -width 55 -height 30 -font {Courier 14} pack .d.lbox -side left scrollbar .d.scroll -command ".d.lbox yview" pack .d.scroll -side right -fill y } wm title .d $select # if we have not already done so - get the version list if { [llength $FileList($name)] == 0 } { # going to take time so make it appear - and/or show new title .d.lbox insert end "Getting version history ..." update set cmd [list |aereport $VersReport -p $ProjName -unf $name] if [ catch {open $cmd r} pfid ] { puts stderr "file history $name failed:$pfid"; } else { # read info from command foreach l [split [read $pfid] \n] { # get rid of excess spaces and skip any blank lines # regsub returns the number of matches if { [regsub -all {[ \t]+} $l { } ln] } { # split into fields set flds [split $ln { }] # make up the entry using some of the fields for looks # example line fields are: # 0 1 2 3 4 5 6 7 # 42 Mon Dec 6 17:26:00 2004 post:64 1.23 # treat time and revision fields as strings set chgid [lindex $flds 6] # No idea why % must be doubled here (another eval?) set entry [format {%%-6s %%02d%%3s%%4d %%-8s %%s} \ [lindex $flds 7] \ [lindex $flds 3] [lindex $flds 2] [lindex $flds 5] \ [lindex $flds 4] $chgid \ ] # get the change/delta argument for this file/version set chdelta [chgArg $chgid [lindex $flds 0]] # stash the change and delta number in argument form # tacked on the end of the change data lappend FileList($name) "$entry~$chdelta" } } close $pfid } } # Clean out any existing messages .d.lbox delete 0 end # OK lets sort and place in display the data portion foreach change [lsort -command $RevSort $FileList($name)] { # select the first data part - skip delta tag along .d.lbox insert end [lindex [split $change ~] 0] } .d.ctrls.go configure -command "doDiff $name .d.lbox" } } proc doDiff { File lb } { global FileList ProjTrunk set versions [$lb curselection] set count [llength $versions] if { $count < 2 } { .d.ctrls.msg configure -text "Please pick TWO versions" } elseif { $count > 2 } { .d.ctrls.msg configure -text "Please, pick only TWO" } else { set cmd [list aediff -p $ProjTrunk] # 0 index is higher on list so actually newer revision set newdat [lindex $FileList($File) [lindex $versions 0]] foreach p [split [lindex [split $newdat ~] 1] { }] { lappend cmd $p } # 1 index is lower on list so older revision set olddat [lindex $FileList($File) [lindex $versions 1]] foreach p [split [lindex [split $olddat ~] 1] { }] { lappend cmd $p } # Finally add the file name itself lappend cmd $File if [ catch {eval exec $cmd} pmsg ] { puts stderr $pmsg } } } # EOF: scripts/aexver.wsh