54d1e3537e 2007-11-10 aku: ## -*- tcl -*- 54d1e3537e 2007-11-10 aku: # # ## ### ##### ######## ############# ##################### 54d1e3537e 2007-11-10 aku: ## Copyright (c) 2007 Andreas Kupries. 54d1e3537e 2007-11-10 aku: # 54d1e3537e 2007-11-10 aku: # This software is licensed as described in the file LICENSE, which 54d1e3537e 2007-11-10 aku: # you should have received as part of this distribution. 54d1e3537e 2007-11-10 aku: # 54d1e3537e 2007-11-10 aku: # This software consists of voluntary contributions made by many 54d1e3537e 2007-11-10 aku: # individuals. For exact contribution history, see the revision 54d1e3537e 2007-11-10 aku: # history and logs, available at http://fossil-scm.hwaci.com/fossil 54d1e3537e 2007-11-10 aku: # # ## ### ##### ######## ############# ##################### 54d1e3537e 2007-11-10 aku: 5f7acef887 2007-11-10 aku: ## Pass V. This pass creates the initial set of project level 5f7acef887 2007-11-10 aku: ## revisions, aka changesets. Later passes will refine them, puts them 5f7acef887 2007-11-10 aku: ## into proper order, set their dependencies, etc. 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: # # ## ### ##### ######## ############# ##################### 54d1e3537e 2007-11-10 aku: ## Requirements 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: package require Tcl 8.4 ; # Required runtime. 54d1e3537e 2007-11-10 aku: package require snit ; # OO system. 54d1e3537e 2007-11-10 aku: package require vc::tools::misc ; # Text formatting. 54d1e3537e 2007-11-10 aku: package require vc::tools::log ; # User feedback. 5f7acef887 2007-11-10 aku: package require vc::fossil::import::cvs::repository ; # Repository management. 54d1e3537e 2007-11-10 aku: package require vc::fossil::import::cvs::state ; # State storage. bf83201c7f 2007-11-27 aku: package require vc::fossil::import::cvs::integrity ; # State integrity checks. 54d1e3537e 2007-11-10 aku: package require vc::fossil::import::cvs::project::sym ; # Project level symbols 5f7acef887 2007-11-10 aku: package require vc::fossil::import::cvs::project::rev ; # Project level changesets 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: # # ## ### ##### ######## ############# ##################### 54d1e3537e 2007-11-10 aku: ## Register the pass with the management 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: vc::fossil::import::cvs::pass define \ 54d1e3537e 2007-11-10 aku: InitCsets \ 54d1e3537e 2007-11-10 aku: {Initialize ChangeSets} \ 54d1e3537e 2007-11-10 aku: ::vc::fossil::import::cvs::pass::initcsets 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: # # ## ### ##### ######## ############# ##################### 54d1e3537e 2007-11-10 aku: ## 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: snit::type ::vc::fossil::import::cvs::pass::initcsets { 54d1e3537e 2007-11-10 aku: # # ## ### ##### ######## ############# 54d1e3537e 2007-11-10 aku: ## Public API 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: typemethod setup {} { 54d1e3537e 2007-11-10 aku: # Define the names and structure of the persistent state of 54d1e3537e 2007-11-10 aku: # this pass. 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: state reading meta 5f7acef887 2007-11-10 aku: state reading revision 95af789e1f 2007-11-10 aku: state reading revisionbranchchildren 5f7acef887 2007-11-10 aku: state reading branch 5f7acef887 2007-11-10 aku: state reading tag 5f7acef887 2007-11-10 aku: state reading symbol 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: # Data per changeset, namely the project it belongs to, how it 5f7acef887 2007-11-10 aku: # was induced (revision or symbol), plus reference to the 5f7acef887 2007-11-10 aku: # primary entry causing it (meta entry or symbol). An adjunct 5f7acef887 2007-11-10 aku: # table translates the type id's into human readable labels. 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: state writing changeset { 5f7acef887 2007-11-10 aku: cid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 5f7acef887 2007-11-10 aku: pid INTEGER NOT NULL REFERENCES project, 5f7acef887 2007-11-10 aku: type INTEGER NOT NULL REFERENCES cstype, 5f7acef887 2007-11-10 aku: src INTEGER NOT NULL -- REFERENCES meta|symbol (type dependent) 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: state writing cstype { 5f7acef887 2007-11-10 aku: tid INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, 5f7acef887 2007-11-10 aku: name TEXT NOT NULL, 5f7acef887 2007-11-10 aku: UNIQUE (name) 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: state run { 5f7acef887 2007-11-10 aku: INSERT INTO cstype VALUES (0,'rev'); 5f7acef887 2007-11-10 aku: INSERT INTO cstype VALUES (1,'sym'); 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: # Map from changesets to the (file level) revisions they 5f7acef887 2007-11-10 aku: # contain. The pos'ition provides an order of the revisions 5f7acef887 2007-11-10 aku: # within a changeset. They are unique within the changeset. 5f7acef887 2007-11-10 aku: # The revisions are in principle unique, if we were looking 5f7acef887 2007-11-10 aku: # only at revision changesets. However a revision can appear 5f7acef887 2007-11-10 aku: # in both revision and symbol changesets, and in multiple 5f7acef887 2007-11-10 aku: # symbol changesets as well. So we can only say that it is 5f7acef887 2007-11-10 aku: # unique within the changeset. 5f7acef887 2007-11-10 aku: # 5f7acef887 2007-11-10 aku: # TODO: Check if integrity checks are possible. 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: state writing csrevision { 5f7acef887 2007-11-10 aku: cid INTEGER NOT NULL REFERENCES changeset, 5f7acef887 2007-11-10 aku: pos INTEGER NOT NULL, 5f7acef887 2007-11-10 aku: rid INTEGER NOT NULL REFERENCES revision, 5f7acef887 2007-11-10 aku: UNIQUE (cid, pos), 5f7acef887 2007-11-10 aku: UNIQUE (cid, rid) 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: project::rev getcstypes 54d1e3537e 2007-11-10 aku: return 54d1e3537e 2007-11-10 aku: } 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: typemethod load {} { 54d1e3537e 2007-11-10 aku: # Pass manager interface. Executed to load data computed by 54d1e3537e 2007-11-10 aku: # this pass into memory when this pass is skipped instead of 54d1e3537e 2007-11-10 aku: # executed. 24c0b662de 2007-11-13 aku: 24c0b662de 2007-11-13 aku: state reading changeset 24c0b662de 2007-11-13 aku: state reading csrevision 24c0b662de 2007-11-13 aku: state reading cstype 24c0b662de 2007-11-13 aku: 24c0b662de 2007-11-13 aku: foreach {id pid cstype srcid} [state run { 341d96be21 2007-11-16 aku: SELECT C.cid, C.pid, CS.name, C.src 341d96be21 2007-11-16 aku: FROM changeset C, cstype CS 341d96be21 2007-11-16 aku: WHERE C.type = CS.tid 24c0b662de 2007-11-13 aku: ORDER BY C.cid 24c0b662de 2007-11-13 aku: }] { 24c0b662de 2007-11-13 aku: set r [project::rev %AUTO% [repository projectof $pid] $cstype $srcid [state run { 24c0b662de 2007-11-13 aku: SELECT C.rid 24c0b662de 2007-11-13 aku: FROM csrevision C 24c0b662de 2007-11-13 aku: WHERE C.cid = $id 24c0b662de 2007-11-13 aku: ORDER BY C.pos 65be27aa69 2007-11-22 aku: }] $id] 24c0b662de 2007-11-13 aku: } 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: project::rev getcstypes 65be27aa69 2007-11-22 aku: project::rev loadcounter 54d1e3537e 2007-11-10 aku: return 54d1e3537e 2007-11-10 aku: } 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: typemethod run {} { 54d1e3537e 2007-11-10 aku: # Pass manager interface. Executed to perform the 54d1e3537e 2007-11-10 aku: # functionality of the pass. 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: state transaction { 24c0b662de 2007-11-13 aku: CreateRevisionChangesets ; # Group file revisions into csets. 24c0b662de 2007-11-13 aku: BreakInternalDependencies ; # Split the csets based on internal conflicts. 24c0b662de 2007-11-13 aku: CreateSymbolChangesets ; # Create csets for tags and branches. 24c0b662de 2007-11-13 aku: PersistTheChangesets 96b7bfb834 2007-11-16 aku: 96b7bfb834 2007-11-16 aku: repository printcsetstatistics bf83201c7f 2007-11-27 aku: integrity changesets 5f7acef887 2007-11-10 aku: } 54d1e3537e 2007-11-10 aku: return 54d1e3537e 2007-11-10 aku: } 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: typemethod discard {} { 54d1e3537e 2007-11-10 aku: # Pass manager interface. Executed for all passes after the 54d1e3537e 2007-11-10 aku: # run passes, to remove all data of this pass from the state, 54d1e3537e 2007-11-10 aku: # as being out of date. 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: state discard changeset 5f7acef887 2007-11-10 aku: state discard cstype 5f7acef887 2007-11-10 aku: state discard csrevision 54d1e3537e 2007-11-10 aku: return 54d1e3537e 2007-11-10 aku: } 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: # # ## ### ##### ######## ############# 54d1e3537e 2007-11-10 aku: ## Internal methods 54d1e3537e 2007-11-10 aku: 24c0b662de 2007-11-13 aku: proc CreateRevisionChangesets {} { 5f7acef887 2007-11-10 aku: log write 3 initcsets {Create changesets based on revisions} 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: # To get the initial of changesets we first group all file 5f7acef887 2007-11-10 aku: # level revisions using the same meta data entry together. As 5f7acef887 2007-11-10 aku: # the meta data encodes not only author and log message, but 5f7acef887 2007-11-10 aku: # also line of development and project we can be sure that 5f7acef887 2007-11-10 aku: # revisions in different project and lines of development are 5f7acef887 2007-11-10 aku: # not grouped together. In contrast to cvs2svn we do __not__ 5f7acef887 2007-11-10 aku: # use distance in time between revisions to break them 5f7acef887 2007-11-10 aku: # apart. We have seen CVS repositories (from SF) where a 5f7acef887 2007-11-10 aku: # single commit contained revisions several hours apart, 5f7acef887 2007-11-10 aku: # likely due to trouble on the server hosting the repository. 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: # We order the revisions here by time, this will help the 5f7acef887 2007-11-10 aku: # later passes (avoids joins later to get at the ordering 5f7acef887 2007-11-10 aku: # info). 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: set n 0 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: set lastmeta {} 5f7acef887 2007-11-10 aku: set lastproject {} 5f7acef887 2007-11-10 aku: set revisions {} 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: # Note: We could have written this loop to create the csets 5f7acef887 2007-11-10 aku: # early, extending them with all their revisions. This 5f7acef887 2007-11-10 aku: # however would mean lots of (slow) method invokations 5f7acef887 2007-11-10 aku: # on the csets. Doing it like this, late creation, means 5f7acef887 2007-11-10 aku: # less such calls. None, but the creation itself. 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: foreach {mid rid pid} [state run { 5f7acef887 2007-11-10 aku: SELECT M.mid, R.rid, M.pid 5f7acef887 2007-11-10 aku: FROM revision R, meta M -- R ==> M, using PK index of M. 5f7acef887 2007-11-10 aku: WHERE R.mid = M.mid 5f7acef887 2007-11-10 aku: ORDER BY M.mid, R.date 5f7acef887 2007-11-10 aku: }] { 5f7acef887 2007-11-10 aku: if {$lastmeta != $mid} { 5f7acef887 2007-11-10 aku: if {[llength $revisions]} { 5f7acef887 2007-11-10 aku: incr n 5f7acef887 2007-11-10 aku: set p [repository projectof $lastproject] 24c0b662de 2007-11-13 aku: project::rev %AUTO% $p rev $lastmeta $revisions 5f7acef887 2007-11-10 aku: set revisions {} 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: set lastmeta $mid 5f7acef887 2007-11-10 aku: set lastproject $pid 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: lappend revisions $rid 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: if {[llength $revisions]} { 5f7acef887 2007-11-10 aku: incr n 5f7acef887 2007-11-10 aku: set p [repository projectof $lastproject] 24c0b662de 2007-11-13 aku: project::rev %AUTO% $p rev $lastmeta $revisions 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: log write 4 initcsets "Created [nsp $n {revision changeset}]" 5f7acef887 2007-11-10 aku: return 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 24c0b662de 2007-11-13 aku: proc CreateSymbolChangesets {} { 5f7acef887 2007-11-10 aku: log write 3 initcsets {Create changesets based on symbols} 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: # Tags and branches induce changesets as well, containing the 5f7acef887 2007-11-10 aku: # revisions they are attached to (tags), or spawned from 5f7acef887 2007-11-10 aku: # (branches). 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: set n 0 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: # First process the tags, then the branches. We know that 5f7acef887 2007-11-10 aku: # their ids do not overlap with each other. 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: set lastsymbol {} 5f7acef887 2007-11-10 aku: set lastproject {} 5f7acef887 2007-11-10 aku: set revisions {} 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: foreach {sid rid pid} [state run { 5f7acef887 2007-11-10 aku: SELECT S.sid, R.rid, S.pid 5f7acef887 2007-11-10 aku: FROM tag T, revision R, symbol S -- T ==> R/S, using PK indices of R, S. 5f7acef887 2007-11-10 aku: WHERE T.rev = R.rid 5f7acef887 2007-11-10 aku: AND T.sid = S.sid 5f7acef887 2007-11-10 aku: ORDER BY S.sid, R.date 5f7acef887 2007-11-10 aku: }] { 5f7acef887 2007-11-10 aku: if {$lastsymbol != $sid} { 5f7acef887 2007-11-10 aku: if {[llength $revisions]} { 5f7acef887 2007-11-10 aku: incr n 5f7acef887 2007-11-10 aku: set p [repository projectof $lastproject] 24c0b662de 2007-11-13 aku: project::rev %AUTO% $p sym $lastsymbol $revisions 5f7acef887 2007-11-10 aku: set revisions {} 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: set lastsymbol $sid 5f7acef887 2007-11-10 aku: set lastproject $pid 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: lappend revisions $rid 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: if {[llength $revisions]} { 5f7acef887 2007-11-10 aku: incr n 5f7acef887 2007-11-10 aku: set p [repository projectof $lastproject] 24c0b662de 2007-11-13 aku: project::rev %AUTO% $p sym $lastsymbol $revisions 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: set lastsymbol {} 5f7acef887 2007-11-10 aku: set lasproject {} 5f7acef887 2007-11-10 aku: set revisions {} 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: foreach {sid rid pid} [state run { 5f7acef887 2007-11-10 aku: SELECT S.sid, R.rid, S.pid 5f7acef887 2007-11-10 aku: FROM branch B, revision R, symbol S -- B ==> R/S, using PK indices of R, S. 5f7acef887 2007-11-10 aku: WHERE B.root = R.rid 5f7acef887 2007-11-10 aku: AND B.sid = S.sid 5f7acef887 2007-11-10 aku: ORDER BY S.sid, R.date 5f7acef887 2007-11-10 aku: }] { 5f7acef887 2007-11-10 aku: if {$lastsymbol != $sid} { 5f7acef887 2007-11-10 aku: if {[llength $revisions]} { 5f7acef887 2007-11-10 aku: incr n 5f7acef887 2007-11-10 aku: set p [repository projectof $lastproject] 24c0b662de 2007-11-13 aku: project::rev %AUTO% $p sym $lastsymbol $revisions 5f7acef887 2007-11-10 aku: set revisions {} 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: set lastsymbol $sid 5f7acef887 2007-11-10 aku: set lastproject $pid 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: lappend revisions $rid 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: if {[llength $revisions]} { 5f7acef887 2007-11-10 aku: incr n 5f7acef887 2007-11-10 aku: set p [repository projectof $lastproject] 24c0b662de 2007-11-13 aku: project::rev %AUTO% $p sym $lastsymbol $revisions 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 5f7acef887 2007-11-10 aku: log write 4 initcsets "Created [nsp $n {symbol changeset}]" 5f7acef887 2007-11-10 aku: return 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 24c0b662de 2007-11-13 aku: proc BreakInternalDependencies {} { 95af789e1f 2007-11-10 aku: # This code operates on the revision changesets created by 95af789e1f 2007-11-10 aku: # 'CreateRevisionChangesets'. As such it has to follow after 95af789e1f 2007-11-10 aku: # it, before the symbol changesets are made. The changesets 95af789e1f 2007-11-10 aku: # are inspected for internal conflicts and any such are broken 95af789e1f 2007-11-10 aku: # by splitting the problematic changeset into multiple 95af789e1f 2007-11-10 aku: # fragments. The results are changesets which have no internal 95af789e1f 2007-11-10 aku: # dependencies, only external ones. 95af789e1f 2007-11-10 aku: 95af789e1f 2007-11-10 aku: log write 3 initcsets {Break internal dependencies} 24c0b662de 2007-11-13 aku: set old [llength [project::rev all]] 95af789e1f 2007-11-10 aku: 24c0b662de 2007-11-13 aku: foreach cset [project::rev all] { 24c0b662de 2007-11-13 aku: $cset breakinternaldependencies 08ebab80cd 2007-11-10 aku: } 95af789e1f 2007-11-10 aku: 24c0b662de 2007-11-13 aku: set n [expr {[llength [project::rev all]] - $old}] 95af789e1f 2007-11-10 aku: log write 4 initcsets "Created [nsp $n {additional revision changeset}]" 95af789e1f 2007-11-10 aku: log write 4 initcsets Ok. 95af789e1f 2007-11-10 aku: return 95af789e1f 2007-11-10 aku: } 95af789e1f 2007-11-10 aku: 24c0b662de 2007-11-13 aku: proc PersistTheChangesets {} { 24c0b662de 2007-11-13 aku: log write 3 initcsets "Saving [nsp [llength [project::rev all]] {initial changeset}] to the persistent state" 5f7acef887 2007-11-10 aku: 24c0b662de 2007-11-13 aku: foreach cset [project::rev all] { 5f7acef887 2007-11-10 aku: $cset persist 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 95af789e1f 2007-11-10 aku: log write 4 initcsets Ok. 5f7acef887 2007-11-10 aku: return 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: # # ## ### ##### ######## ############# 54d1e3537e 2007-11-10 aku: ## Configuration 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: pragma -hasinstances no ; # singleton 54d1e3537e 2007-11-10 aku: pragma -hastypeinfo no ; # no introspection 54d1e3537e 2007-11-10 aku: pragma -hastypedestroy no ; # immortal 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: # # ## ### ##### ######## ############# 54d1e3537e 2007-11-10 aku: } 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: namespace eval ::vc::fossil::import::cvs::pass { 54d1e3537e 2007-11-10 aku: namespace export initcsets 54d1e3537e 2007-11-10 aku: namespace eval initcsets { 5f7acef887 2007-11-10 aku: namespace import ::vc::fossil::import::cvs::repository 54d1e3537e 2007-11-10 aku: namespace import ::vc::fossil::import::cvs::state bf83201c7f 2007-11-27 aku: namespace import ::vc::fossil::import::cvs::integrity 5f7acef887 2007-11-10 aku: namespace eval project { 5f7acef887 2007-11-10 aku: namespace import ::vc::fossil::import::cvs::project::rev 5f7acef887 2007-11-10 aku: } 5f7acef887 2007-11-10 aku: namespace import ::vc::tools::misc::* 54d1e3537e 2007-11-10 aku: namespace import ::vc::tools::log 54d1e3537e 2007-11-10 aku: log register initcsets 54d1e3537e 2007-11-10 aku: } 54d1e3537e 2007-11-10 aku: } 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: # # ## ### ##### ######## ############# ##################### 54d1e3537e 2007-11-10 aku: ## Ready 54d1e3537e 2007-11-10 aku: 54d1e3537e 2007-11-10 aku: package provide vc::fossil::import::cvs::pass::initcsets 1.0 54d1e3537e 2007-11-10 aku: return