72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: namespace eval ::vc::cvs::ws::branch {} 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # Trivial storage of all branch data as a rectangular table. We can 72dac950c3 2007-09-26 aku: # think up a better suited storage system later, when we know what 72dac950c3 2007-09-26 aku: # type of queries are made to this module. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: proc ::vc::cvs::ws::branch::def {f dv deflist} { 72dac950c3 2007-09-26 aku: upvar 1 $dv date 72dac950c3 2007-09-26 aku: variable bra 72dac950c3 2007-09-26 aku: foreach {tag rev} $deflist { 72dac950c3 2007-09-26 aku: # ignore non-branch tags 72dac950c3 2007-09-26 aku: if {[llength [split $rev .]] < 4} continue 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: if 0 { 72dac950c3 2007-09-26 aku: if { ($rev ne "1.1.1.1") && ![string match *.0.2 $rev] } { 72dac950c3 2007-09-26 aku: # 1.1.1.1 is the base of vendor branches, usually. *.0.y 72dac950c3 2007-09-26 aku: # is the base of regular branches where nothing is on the 72dac950c3 2007-09-26 aku: # branch yet, only its root is marked. Everything else is 72dac950c3 2007-09-26 aku: # noteworthy for now. 72dac950c3 2007-09-26 aku: puts $f/$rev/$tag 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: set root [revroot $rev] 72dac950c3 2007-09-26 aku: lappend bra [list $date($root) $tag $f $rev] 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: proc ::vc::cvs::ws::branch::revroot {rev} { 72dac950c3 2007-09-26 aku: return [join [lrange [split $rev .] 0 end-2] .] 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # ! Files in a branch can appear only after their root revision 72dac950c3 2007-09-26 aku: # exists. This can be checked against the time of the cset which 72dac950c3 2007-09-26 aku: # is our base. Branches which have no files yet can be eliminated 72dac950c3 2007-09-26 aku: # from consideration. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # ! All files noted by the base cset as added/modified have to be 72dac950c3 2007-09-26 aku: # in the branch root. Branches which do not have such a file can 72dac950c3 2007-09-26 aku: # be eliminated from consideration. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # ! The versions of the added/modified files in the base have 72dac950c3 2007-09-26 aku: # match the versions in the branch root. In the sense that they 72dac950c3 2007-09-26 aku: # have to be equal or sucessors. The later implies identity in the 72dac950c3 2007-09-26 aku: # upper parts (only the last 2 parts are relevant), and equal 72dac950c3 2007-09-26 aku: # length. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # This gives us the branch, and, due to the time information a 72dac950c3 2007-09-26 aku: # signature for the root. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: #? Can search for the root based on this signature fail ? 72dac950c3 2007-09-26 aku: # Yes. Because the signature may contain files which were not 72dac950c3 2007-09-26 aku: # actually yet in the root, despite being able to. And which were 72dac950c3 2007-09-26 aku: # not modified by the base, so the check 2 above still passes. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # -> Search for the full signature first, then drop the youngest 72dac950c3 2007-09-26 aku: # files, search again until match. Check the result against the 72dac950c3 2007-09-26 aku: # base, that all needed files are present. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # However - Can search for the root based on the cset data (needed 72dac950c3 2007-09-26 aku: # files). Gives us another set of candidate roots. Intersect! 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: proc ::vc::cvs::ws::branch::find {csvalue} { 72dac950c3 2007-09-26 aku: array set cs $csvalue 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: #variable bra 72dac950c3 2007-09-26 aku: #puts ___________________________________________ 72dac950c3 2007-09-26 aku: #puts [join [lsort -index 0 [lsort -index 1 $bra]] \n] 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: Signatures bd [TimeRelevant $cs(date)] 72dac950c3 2007-09-26 aku: DropIncomplete bd [concat $cs(added) $cs(changed)] 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: #puts ___________________________________________ 72dac950c3 2007-09-26 aku: #parray bd 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: if {[array size bd] < 1} { 72dac950c3 2007-09-26 aku: puts "NO BRANCH" 72dac950c3 2007-09-26 aku: # Deal how? 72dac950c3 2007-09-26 aku: # - Abort 72dac950c3 2007-09-26 aku: # - Ignore this changeset and try the next one 72dac950c3 2007-09-26 aku: # (Which has higher probability of not matching as it might 72dac950c3 2007-09-26 aku: # be the successor in the branch to this cset and not a base). 72dac950c3 2007-09-26 aku: puts "" 72dac950c3 2007-09-26 aku: parray cs 72dac950c3 2007-09-26 aku: exit 72dac950c3 2007-09-26 aku: } elseif {[array size bd] > 1} { 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # While we might have found several tag they may all refer to 72dac950c3 2007-09-26 aku: # the same set of files. If that is so we consider them 72dac950c3 2007-09-26 aku: # identical and take one as representative of all. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: set su {} 72dac950c3 2007-09-26 aku: foreach {t s} [array get bd] { 72dac950c3 2007-09-26 aku: lappend su [DictSort $s] 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: if {[llength [lsort -unique $su]] > 1} { 72dac950c3 2007-09-26 aku: puts "AMBIGOUS. The following branches match:" 72dac950c3 2007-09-26 aku: # Deal how? S.a. 72dac950c3 2007-09-26 aku: puts \t[join [array names bd] \n\t] 72dac950c3 2007-09-26 aku: puts "" 72dac950c3 2007-09-26 aku: parray cs 72dac950c3 2007-09-26 aku: exit 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: # Fall through ... 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: set tg [lindex [array names bd] 0] 72dac950c3 2007-09-26 aku: set rs [RootOf $bd($tg)] 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: #puts "BRANCH = $tg" 72dac950c3 2007-09-26 aku: #puts "ROOTSG = $rs" 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: return [list $tg $rs] 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: proc ::vc::cvs::ws::branch::has {ts needed} { 72dac950c3 2007-09-26 aku: #variable bra 72dac950c3 2007-09-26 aku: #puts ___________________________________________ 72dac950c3 2007-09-26 aku: #puts [join [lsort -index 0 [lsort -index 1 $bra]] \n] 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: Signatures bd [TimeRelevant $ts] 72dac950c3 2007-09-26 aku: DropIncomplete bd $needed 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: #puts ___________________________________________ 72dac950c3 2007-09-26 aku: #parray bd 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: if {[array size bd] < 1} { 72dac950c3 2007-09-26 aku: puts "NO BRANCH" 72dac950c3 2007-09-26 aku: # Deal how? 72dac950c3 2007-09-26 aku: # - Abort 72dac950c3 2007-09-26 aku: # - Ignore this changeset and try the next one 72dac950c3 2007-09-26 aku: # (Which has higher probability of not matching as it might 72dac950c3 2007-09-26 aku: # be the successor in the branch to this cset and not a base). 72dac950c3 2007-09-26 aku: exit 72dac950c3 2007-09-26 aku: } elseif {[array size bd] > 1} { 72dac950c3 2007-09-26 aku: puts "AMBIGOUS. Following branches match:" 72dac950c3 2007-09-26 aku: # Deal how? S.a. 72dac950c3 2007-09-26 aku: puts \t[join [array names bd] \n\t] 72dac950c3 2007-09-26 aku: exit 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: set tg [lindex [array names bd] 0] 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: #puts "BRANCH = $tg" 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: return $tg 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: proc ::vc::cvs::ws::branch::RootOf {dict} { 72dac950c3 2007-09-26 aku: set res {} 72dac950c3 2007-09-26 aku: foreach {f r} $dict { 72dac950c3 2007-09-26 aku: lappend res $f [revroot $r] 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: return $res 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: proc ::vc::cvs::ws::branch::DictSort {dict} { 72dac950c3 2007-09-26 aku: array set a $dict 72dac950c3 2007-09-26 aku: set r {} 72dac950c3 2007-09-26 aku: foreach k [lsort [array names a]] { 72dac950c3 2007-09-26 aku: lappend r $k $a($k) 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: return $r 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: proc ::vc::cvs::ws::branch::DropIncomplete {bv needed} { 72dac950c3 2007-09-26 aku: upvar 1 $bv bdata 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # Check the needed files against the branch signature. If files 72dac950c3 2007-09-26 aku: # are missing or not of a matching version drop the branch from 72dac950c3 2007-09-26 aku: # further consideration. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: foreach {tag sig} [array get bdata] { 72dac950c3 2007-09-26 aku: array set rev $sig 72dac950c3 2007-09-26 aku: foreach {file rv} $needed { 72dac950c3 2007-09-26 aku: if {![info exists rev($file)] || ![successor $rv $rev($file)]} { 72dac950c3 2007-09-26 aku: # file in cset is not in the branch or is present, but 72dac950c3 2007-09-26 aku: # not proper version (different lengths, not matching 72dac950c3 2007-09-26 aku: # in upper 0..end-2 parts, not equal|successor). 72dac950c3 2007-09-26 aku: unset bdata($tag) 72dac950c3 2007-09-26 aku: break 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: continue 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: unset rev 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: return 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: proc ::vc::cvs::ws::branch::successor {ra rb} { 72dac950c3 2007-09-26 aku: # a successor-of b ? 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: set la [split $ra .] 72dac950c3 2007-09-26 aku: set lb [split $rb .] 72dac950c3 2007-09-26 aku: if { 72dac950c3 2007-09-26 aku: ([llength $la] != [llength $lb]) || 72dac950c3 2007-09-26 aku: ([lrange $la 0 end-2] ne [lrange $lb 0 end-2]) || 72dac950c3 2007-09-26 aku: ([package vcompare $ra $rb] < 0) 72dac950c3 2007-09-26 aku: } { 72dac950c3 2007-09-26 aku: return 0 72dac950c3 2007-09-26 aku: } else { 72dac950c3 2007-09-26 aku: return 1 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 7a64b9e738 2007-09-27 aku: proc ::vc::cvs::ws::branch::rootSuccessor {ra rb} { 7a64b9e738 2007-09-27 aku: # a root-successor-of b ? (<=> b root version of a ?) 7a64b9e738 2007-09-27 aku: 7a64b9e738 2007-09-27 aku: if {$rb eq [revroot $ra]} { 7a64b9e738 2007-09-27 aku: return 1 7a64b9e738 2007-09-27 aku: } else { 7a64b9e738 2007-09-27 aku: return 0 7a64b9e738 2007-09-27 aku: } 7a64b9e738 2007-09-27 aku: } 7a64b9e738 2007-09-27 aku: 72dac950c3 2007-09-26 aku: proc ::vc::cvs::ws::branch::Signatures {bv deflist} { 72dac950c3 2007-09-26 aku: upvar 1 $bv bdata 72dac950c3 2007-09-26 aku: # Sort branch data by symbolic name for the upcoming checks, and 72dac950c3 2007-09-26 aku: # generate file revision signatures. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: array set bdata {} 72dac950c3 2007-09-26 aku: foreach item $deflist { 72dac950c3 2007-09-26 aku: # item = timestamp tag file revision 72dac950c3 2007-09-26 aku: foreach {__ tag file rev} $item break 72dac950c3 2007-09-26 aku: lappend bdata($tag) $file $rev 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: #puts ___________________________________________ 72dac950c3 2007-09-26 aku: #parray bdata 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: return 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: proc ::vc::cvs::ws::branch::TimeRelevant {date} { 72dac950c3 2007-09-26 aku: variable bra 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # Retrieve the branch data which definitely comes before (in time) 72dac950c3 2007-09-26 aku: # the candidate cset. Only this set is relevant to further checks 72dac950c3 2007-09-26 aku: # and filters. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: set res {} 72dac950c3 2007-09-26 aku: foreach item $bra { 72dac950c3 2007-09-26 aku: # item = timestamp tag file revision 72dac950c3 2007-09-26 aku: # 0 1 2 3 72dac950c3 2007-09-26 aku: if {[package vcompare [lindex $item 0] $date] > 0} continue 72dac950c3 2007-09-26 aku: lappend res $item 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: #puts ___________________________________________ 72dac950c3 2007-09-26 aku: #puts [join [lsort -index 0 [lsort -index 1 $res]] \n] 72dac950c3 2007-09-26 aku: return $res 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: namespace eval ::vc::cvs::ws::branch { 72dac950c3 2007-09-26 aku: variable bra {} 72dac950c3 2007-09-26 aku: 7a64b9e738 2007-09-27 aku: namespace export def find successor rootSuccessor revroot has 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: package provide vc::cvs::ws::branch 1.0 72dac950c3 2007-09-26 aku: return 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # Queries ... 72dac950c3 2007-09-26 aku: # - Get set of files and revs for branch B which can be in it by the time T 72dac950c3 2007-09-26 aku: # - Check if a file referenced a/m instruction is in a set of files 72dac950c3 2007-09-26 aku: # and revision, identical or proper sucessor. 72dac950c3 2007-09-26 aku: # => Combination 72dac950c3 2007-09-26 aku: # Can branch B match the cset file a/m at time T ? 72dac950c3 2007-09-26 aku: # => Full combination 72dac950c3 2007-09-26 aku: # Give me the list of branches which can match the cset file a/m 72dac950c3 2007-09-26 aku: # at time T. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: # Branch DB organization => (Tag -> (Time -> (File -> Rev))) 72dac950c3 2007-09-26 aku: # The full combination actually does not need a complex structure. 72dac950c3 2007-09-26 aku: # We can simply scan a plain list of branch data. 72dac950c3 2007-09-26 aku: # The only alternative is an inverted index. 72dac950c3 2007-09-26 aku: # Time -> ((File -> Rev) -> Tag). Difficult to process. 72dac950c3 2007-09-26 aku: # Linear scan: 72dac950c3 2007-09-26 aku: # - Time after T => drop 72dac950c3 2007-09-26 aku: # - File !in a/m => drop 72dac950c3 2007-09-26 aku: # - Version !match => drop 72dac950c3 2007-09-26 aku: # -- Collect tag 72dac950c3 2007-09-26 aku: # Then lsort -unique for our result. 72dac950c3 2007-09-26 aku: # NO - The file check is inverted - All files have to be in a/m for the base, not a/m in files 72dac950c3 2007-09-26 aku: # == - This also breaks the issue for same-branch detection - 72dac950c3 2007-09-26 aku: # future csets in the branch do not have that property. 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: puts ___________________________________________ 72dac950c3 2007-09-26 aku: # Show only branch data which definitely comes before the 72dac950c3 2007-09-26 aku: # candidate cset 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: array set n [concat $cs(added) $cs(changed)] 72dac950c3 2007-09-26 aku: set xx {} 72dac950c3 2007-09-26 aku: set bb {} 72dac950c3 2007-09-26 aku: ::foreach x $bra { 72dac950c3 2007-09-26 aku: ::foreach {ts tag f r} $x break 72dac950c3 2007-09-26 aku: if {[package vcompare $ts $cs(date)] > 0} continue 72dac950c3 2007-09-26 aku: if {![info exists n($f)]} continue 72dac950c3 2007-09-26 aku: if { 72dac950c3 2007-09-26 aku: ([llength [split $n($f) .]] != [llength [split $r .]]) || 72dac950c3 2007-09-26 aku: ([lrange [split $n($f) .] 0 end-2] ne [lrange [split $r .] 0 end-2]) || 72dac950c3 2007-09-26 aku: ([package vcompare $n($f) $r] < 0) 72dac950c3 2007-09-26 aku: } continue 72dac950c3 2007-09-26 aku: lappend xx $x 72dac950c3 2007-09-26 aku: lappend bb $tag 72dac950c3 2007-09-26 aku: } 72dac950c3 2007-09-26 aku: puts [join [lsort -index 0 [lsort -index 1 $xx]] \n] 72dac950c3 2007-09-26 aku: puts [join [lsort -unique $bb] \n] 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: exit 72dac950c3 2007-09-26 aku: 72dac950c3 2007-09-26 aku: