package versiontree public class VersionTree { static objref GridMgr gridmgr static objref VersionMgr vermgr static tclbool shortform static tclbool warnings 1 static tclbool quiet static public tclstring selitem "(None)" public static void main {args} { # parse arguments parseArgs $args # create the version manager set vermgr [new VersionMgr] # parse version information parseVersions # display the tree #::puts "time to output tree: [time {outputTree}]" outputTree tkwait window . } # overload the puts command static void puts {msg} { if { $quiet } { return } if { [string range $msg 0 7] == "Warning:" && $warnings == 0 } { return } ::puts $msg } private static void parseArgs {argv} { for {set argc 0} {[string match -* [lindex $argv $argc]]} {incr argc} { switch -exact -- [lindex $argv $argc] { -version - -V { puts "VersionTree v1.0" exit 0 } -s { set shortform 1 } -w { set warnings 0 } -q { set quiet 1 } } } } private static void parseVersions {} { global env if { ! [info exists env(FAKEPRCS)] } { # find out what the project name is set projfile [glob -nocomplain *.prj] if { [llength $projfile] != 1 } { puts "Error: no project file or more than one" exit 1 } set proj [file rootname [lindex $projfile 0]] puts "reading PRCS info..." set f [open "|prcs info -l --sort date" r] set buf [read $f] close $f puts "parsing PRCS info..." tclstring version tcllist parents foreach line [split $buf "\n"] { if { [string match "$proj *" $line] } { set newversion [lindex $line 1] # double check to make sure it is a real version line if { ! [regexp {^.*\.[0-9]+$} $newversion] } continue if { $version != "" } { # take care of the previous one $vermgr addVersion $version $parents set version "" set parents {} } set version $newversion } elseif { [string match "Parent-Version:*" $line] } { lappend parents [lindex $line 1] } } # flush the last entry if { $version != "" } { $vermgr addVersion $version $parents } } else { puts "Creating fake version information..." $vermgr addVersion 1.0.1 {} $vermgr addVersion 1.0.2 {1.0.1} $vermgr addVersion feature.1 {1.0.2} $vermgr addVersion feature.2 {feature.1} $vermgr addVersion feature.3 {feature.2} $vermgr addVersion feature2.1 {1.0.2} $vermgr addVersion feature2.2 {feature2.1} $vermgr addVersion 1.0.3 {1.0.2 feature.1} $vermgr addVersion 1.0.5 {1.0.4 feature2.2} $vermgr addVersion 1.0.6 {1.0.5} $vermgr addVersion 2.0.1 {1.0.4.1} } } private static void outputTree {} { puts "Building tree..." # create our version selected listener objref VersionListener listener [new VersionListener] set f [frame .extra] pack $f -pady 5 -fill x -expand no label $f.l1 -text "Current selected item:" label $f.l2 -text "" -textvariable [teafield $listener selitem] button $f.b1 -text "Print" -command "$this printcmd" button $f.b2 -text "Exit" -command "destroy ." pack $f.l1 -side left -anchor w pack $f.l2 -side left -anchor w pack $f.b2 -side right -anchor e pack $f.b1 -side right -anchor e -padx 30 # first create the canvas frame .grid pack .grid -expand yes -fill both -padx 3 -pady 3 grid rowconfig .grid 0 -weight 1 -minsize 0 grid columnconfig .grid 0 -weight 1 -minsize 0 set c [canvas .c -scrollregion {0c 0c 250c 120c} -height 15c -width 15c\ -xscrollcommand ".hscroll set" \ -yscrollcommand ".vscroll set" \ -background #f0f0f0 -borderwidth 2 -relief solid] scrollbar .hscroll -orient horiz -command "$c xview" scrollbar .vscroll -command "$c yview" grid .c -padx 4 -in .grid -pady 4 -row 0 -column 0 -sticky news grid .vscroll -in .grid -padx 1 -pady 1 -row 0 -column 1 -sticky news grid .hscroll -in .grid -padx 1 -pady 1 -row 1 -column 0 -sticky news # create the grid manager set gridmgr [new GridMgr $c] # add listener to the grid mgr's listener list $gridmgr addListener $listener # now let's traverse the tree set col -1 foreach orphan [$vermgr getOrphans] { traverse $orphan $col 0 set col [$gridmgr getLastCol] } # handle the merge arrows foreach orphan [$vermgr getOrphans] { if { $orphan != "null" } { traverseMerges $orphan } } # now tell the gridmgr to draw all his grid items now that the arrows # and lines are in place $gridmgr drawAllItems # readjust the scroll region #set canvsize [$gridmgr getSize] #.c configure -scrollregion [list 0c 0c [lindex $canvsize 0] [lindex $canvsize 1]] .c configure -scrollregion [.c bbox all] } private static GridItem traverse {Branch.br tclint.col tclint.row} { # bump up the grid column number incr col # ask the grid manager for a chunk big enough for this branch $gridmgr need [$br getDepth] col row objref GridItem rci objref GridItem i tclbool first 1 set rci [$gridmgr addItem Rectangle $col $row $br] $rci setText [$br getName] objref Snapshot ss tcllist children [$br getChildren] tclint count [llength $children] tclint j foreach ss $children { incr j # if this snapshot has no references, then don't bother outputting it # but do it if it is the last one if { $shortform && [$ss getReferences] == 0 && $j != $count } { continue } incr row set i [$gridmgr addItem Circle $col $row $ss] $i setText [$ss getNum] # add the grid item to the version manager $vermgr mapGridItem [$ss getName] $i # now traverse over this snapshot traverse $i $ss $col $row if { $first } { # connect to the feature branch box $gridmgr addConnector $rci $i set first 0 } } return $rci } private static void traverse {GridItem.i Snapshot.ss tclint.col tclint.row} { objref Branch br objref GridItem pi # take care of vertical parent connection objref Snapshot vparent [$ss getVParent] if { $vparent != "null" } { set pi [$vermgr getGridItem [$vparent getName]] if { $pi == "null" } { # don't output this if the short form is being used #puts "Warning: no grid item for [$vparent getName]" } { $gridmgr addConnector $pi $i } } # do the horizontal branches foreach br [$ss getBranches] { set bi [traverse $br $col $row] $gridmgr addConnector $i $bi incr col incr row } } private static void traverseMerges {Branch.br} { objref Snapshot ss foreach ss [$br getChildren] { objref GridItem si [$vermgr getGridItem [$ss getName]] if { $si == "null" && [$ss getMergeParents] != "" } { puts "Warning: version [$ss getName] doesn't seem to have a grid item" continue } # handle merge arrows objref Snapshot mp foreach mp [$ss getMergeParents] { set pi [$vermgr getGridItem [$mp getName]] if { $pi == "null" } { puts "Warning: no grid item for merge parent [$mp getName] merging to [$ss getName]" } { $gridmgr addConnector $pi $si 1 } } # do any branches we may have foreach ssbr [$ss getBranches] { traverseMerges $ssbr } } } public static void printcmd {} { $gridmgr print } } class VersionListener implements SelectedVersionListener { public tclstring selitem "(None)" void snapshotSelected {Snapshot.selected} { set selitem "Version [$selected getName]" } void snapshotUnSelected {Snapshot.selected} { set selitem "(None)" } void branchSelected {Branch.selected} { set selitem "Branch [$selected getName]" } void branchUnSelected {Branch.selected} { set selitem "(None)" } }