Fossil SCM

fossil-scm / tools / cvs2fossil / lib / c2f_state.tcl
Source Blame History 231 lines
eb656de… aku 1 ## -*- tcl -*-
eb656de… aku 2 # # ## ### ##### ######## ############# #####################
eb656de… aku 3 ## Copyright (c) 2007 Andreas Kupries.
eb656de… aku 4 #
eb656de… aku 5 # This software is licensed as described in the file LICENSE, which
eb656de… aku 6 # you should have received as part of this distribution.
eb656de… aku 7 #
eb656de… aku 8 # This software consists of voluntary contributions made by many
eb656de… aku 9 # individuals. For exact contribution history, see the revision
eb656de… aku 10 # history and logs, available at http://fossil-scm.hwaci.com/fossil
eb656de… aku 11 # # ## ### ##### ######## ############# #####################
eb656de… aku 12
eb656de… aku 13 ## State manager. Maintains the sqlite database used by all the other
eb656de… aku 14 ## parts of the system, especially the passes and their support code,
eb656de… aku 15 ## to persist and restore their state across invokations.
eb656de… aku 16
eb656de… aku 17 # # ## ### ##### ######## ############# #####################
eb656de… aku 18 ## Requirements
eb656de… aku 19
eb656de… aku 20 package require Tcl 8.4 ; # Required runtime.
eb656de… aku 21 package require snit ; # OO system.
eb656de… aku 22 package require fileutil ; # File operations.
eb656de… aku 23 package require sqlite3 ; # Database access.
eb656de… aku 24 package require vc::tools::trouble ; # Error reporting.
eb656de… aku 25 package require vc::tools::log ; # User feedback.
eb656de… aku 26
eb656de… aku 27 # # ## ### ##### ######## ############# #####################
b679ca3… aku 28 ##
eb656de… aku 29
eb656de… aku 30 snit::type ::vc::fossil::import::cvs::state {
eb656de… aku 31 # # ## ### ##### ######## #############
eb656de… aku 32 ## Public API
eb656de… aku 33
e288af3… aku 34 typemethod usedb {path} {
eb656de… aku 35 # Immediate validation. There are are two possibilities to
eb656de… aku 36 # consider. The path exists or it doesn't.
eb656de… aku 37
eb656de… aku 38 # In the first case it has to be a readable and writable file,
eb656de… aku 39 # and it has to be a proper sqlite database. Further checks
eb656de… aku 40 # regarding the required tables will be done later, by the
eb656de… aku 41 # passes, during their setup.
eb656de… aku 42
eb656de… aku 43 # In the second case we have to be able to create the file,
eb656de… aku 44 # and check that. This is done by opening it, sqlite will then
eb656de… aku 45 # try to create it, and may fail.
eb656de… aku 46
7208c7a… mjanssen 47 if {[::file exists $path]} {
eb656de… aku 48 if {![fileutil::test $path frw msg {cvs2fossil state}]} {
eb656de… aku 49 trouble fatal $msg
eb656de… aku 50 return
eb656de… aku 51 }
eb656de… aku 52 }
eb656de… aku 53
eb656de… aku 54 if {[catch {
eb656de… aku 55 sqlite3 ${type}::TEMP $path
7208c7a… mjanssen 56 ${type}::TEMP eval {PRAGMA synchronous=OFF;}
eb656de… aku 57 } res]} {
eb656de… aku 58 trouble fatal $res
eb656de… aku 59 return
eb656de… aku 60 }
eb656de… aku 61
eb656de… aku 62 # A previously defined state database is closed before
eb656de… aku 63 # committing to the new definition. We do not store the path
eb656de… aku 64 # itself, this ensures that the file is _not_ cleaned up after
eb656de… aku 65 # a run.
eb656de… aku 66
fb1e36d… aku 67 set mystate ${type}::STATE
fb1e36d… aku 68 set mypath {}
fb1e36d… aku 69
fb1e36d… aku 70 catch { $mystate close }
fb1e36d… aku 71 rename ${type}::TEMP $mystate
eb656de… aku 72
fb1e36d… aku 73 log write 2 state "is $path"
eb656de… aku 74 return
eb656de… aku 75 }
eb656de… aku 76
eb656de… aku 77 typemethod setup {} {
eb656de… aku 78 # If, and only if no state database was defined by the user
eb656de… aku 79 # then it is now the time to create our own using a tempfile.
eb656de… aku 80
fb1e36d… aku 81 if {$mystate ne ""} return
eb656de… aku 82
eb656de… aku 83 set mypath [fileutil::tempfile cvs2fossil_state_]
fb1e36d… aku 84 set mystate ${type}::STATE
fb1e36d… aku 85 sqlite3 $mystate $mypath
7208c7a… mjanssen 86 $mystate eval {PRAGMA synchronous=OFF;}
eb656de… aku 87
eb656de… aku 88 log write 2 state "using $mypath"
eb656de… aku 89 return
eb656de… aku 90 }
eb656de… aku 91
eb656de… aku 92 typemethod release {} {
eb656de… aku 93 log write 2 state release
eb656de… aku 94 ${type}::STATE close
eb656de… aku 95 if {$mypath eq ""} return
7208c7a… mjanssen 96 ::file delete $mypath
fb1e36d… aku 97 return
fb1e36d… aku 98 }
fb1e36d… aku 99
e288af3… aku 100 # Declare a table needed for the storing of persistent state, and
e288af3… aku 101 # its structure. A possibly previously existing definition is
e288af3… aku 102 # dropped. To be used when a table is needed and not assumed to
e288af3… aku 103 # exist from previous passes.
10f9d51… aku 104
e288af3… aku 105 typemethod extend {name definition {indices {}}} {
e288af3… aku 106 log write 5 state "extend $name"
e288af3… aku 107 Save "extend $name ================================"
fb1e36d… aku 108
fb1e36d… aku 109 $mystate transaction {
fb1e36d… aku 110 catch { $mystate eval "DROP TABLE $name" }
fb1e36d… aku 111 $mystate eval "CREATE TABLE $name ( $definition )"
74854a3… aku 112
74854a3… aku 113 set id 0
74854a3… aku 114 foreach columns $indices {
e288af3… aku 115 log write 5 state "index $name$id"
74854a3… aku 116
74854a3… aku 117 $mystate eval "CREATE INDEX ${name}$id ON ${name} ( [join $columns ,] )"
74854a3… aku 118 incr id
74854a3… aku 119 }
fb1e36d… aku 120 }
fb1e36d… aku 121 return
fb1e36d… aku 122 }
fb1e36d… aku 123
e288af3… aku 124 # Declare that a table is needed for reading from and/or storing
e288af3… aku 125 # to persistent state, and is assumed to already exist. A missing
e288af3… aku 126 # table is an internal error causing an immediate exit.
10f9d51… aku 127
e288af3… aku 128 typemethod use {name} {
e288af3… aku 129 log write 5 state "use $name"
e288af3… aku 130 Save "use $name ==================================="
fb1e36d… aku 131
fb1e36d… aku 132 set found [llength [$mystate eval {
fb1e36d… aku 133 SELECT name
fb1e36d… aku 134 FROM sqlite_master
fb1e36d… aku 135 WHERE type = 'table'
fb1e36d… aku 136 AND name = $name
fb1e36d… aku 137 ;
fb1e36d… aku 138 }]]
fb1e36d… aku 139
47d52d1… aku 140 # No assert, would cause cycle in package dependencies
fb1e36d… aku 141 if {$found} return
fb1e36d… aku 142 trouble internal "The required table \"$name\" is not defined."
fb1e36d… aku 143 # Not reached
fb1e36d… aku 144 return
fb1e36d… aku 145 }
fb1e36d… aku 146
ae19c0f… aku 147 typemethod discard {name} {
ae19c0f… aku 148 # Method for a user to remove outdated information from the
ae19c0f… aku 149 # persistent state, table by table.
ae19c0f… aku 150
e288af3… aku 151 log write 5 state "discard $name"
ae19c0f… aku 152
ae19c0f… aku 153 $mystate transaction {
ae19c0f… aku 154 catch { $mystate eval "DROP TABLE $name" }
ae19c0f… aku 155 }
ae19c0f… aku 156 return
ae19c0f… aku 157 }
ae19c0f… aku 158
fb1e36d… aku 159 typemethod run {args} {
e288af3… aku 160 Save $args
fb1e36d… aku 161 return [uplevel 1 [linsert $args 0 $mystate eval]]
6559f32… aku 162 }
6559f32… aku 163
6559f32… aku 164 typemethod foreachrow {sql script} {
6559f32… aku 165 Save $sql
6559f32… aku 166 uplevel 1 [list $mystate eval $sql $script]
6559f32… aku 167 return
e288af3… aku 168 }
e288af3… aku 169
96b7bfb… aku 170 typemethod one {args} {
e288af3… aku 171 Save $args
e288af3… aku 172 return [uplevel 1 [linsert $args 0 $mystate onecolumn]]
042d54b… aku 173 }
042d54b… aku 174
042d54b… aku 175 typemethod transaction {script} {
042d54b… aku 176 return [uplevel 1 [list $mystate transaction $script]]
042d54b… aku 177 }
042d54b… aku 178
042d54b… aku 179 typemethod id {} {
042d54b… aku 180 return [$mystate last_insert_rowid]
042d54b… aku 181 }
042d54b… aku 182
e288af3… aku 183 typemethod savequeriesto {path} {
e288af3… aku 184 set mysavepath $path
e288af3… aku 185 return
e288af3… aku 186 }
e288af3… aku 187
e288af3… aku 188 # # ## ### ##### ######## #############
e288af3… aku 189
e288af3… aku 190 proc Save {text} {
e288af3… aku 191 ::variable mysavepath
e288af3… aku 192 if {$mysavepath eq ""} return
e288af3… aku 193 fileutil::appendToFile $mysavepath $text\n\n
e288af3… aku 194 return
e288af3… aku 195 }
e288af3… aku 196
eb656de… aku 197 # # ## ### ##### ######## #############
eb656de… aku 198 ## State
eb656de… aku 199
e288af3… aku 200 typevariable mystate {} ; # Sqlite database (command) holding the converter state.
e288af3… aku 201 typevariable mypath {} ; # Path to the database, for cleanup of a temp database.
e288af3… aku 202 typevariable mysavepath {} ; # Path where to save queries for introspection.
eb656de… aku 203
eb656de… aku 204 # # ## ### ##### ######## #############
eb656de… aku 205 ## Internal methods
eb656de… aku 206
eb656de… aku 207
eb656de… aku 208 # # ## ### ##### ######## #############
eb656de… aku 209 ## Configuration
eb656de… aku 210
eb656de… aku 211 pragma -hasinstances no ; # singleton
eb656de… aku 212 pragma -hastypeinfo no ; # no introspection
eb656de… aku 213 pragma -hastypedestroy no ; # immortal
eb656de… aku 214
eb656de… aku 215 # # ## ### ##### ######## #############
eb656de… aku 216 }
eb656de… aku 217
eb656de… aku 218 namespace eval ::vc::fossil::import::cvs {
eb656de… aku 219 namespace export state
eb656de… aku 220 namespace eval state {
eb656de… aku 221 namespace import ::vc::tools::trouble
eb656de… aku 222 namespace import ::vc::tools::log
eb656de… aku 223 log register state
eb656de… aku 224 }
eb656de… aku 225 }
eb656de… aku 226
eb656de… aku 227 # # ## ### ##### ######## ############# #####################
eb656de… aku 228 ## Ready
eb656de… aku 229
eb656de… aku 230 package provide vc::fossil::import::cvs::state 1.0
eb656de… aku 231 return

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button