Fossil SCM

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

Keyboard Shortcuts

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