Fossil SCM

Updated my notes regarding memory usage. Converted more locations to incremental query processing via 'state foreachrow', now throughout the importer.

aku 2008-02-24 18:01 trunk
Commit f637d4220695430e25040509f12f050d2f4cd42f
+26 -48
--- cvs2fossil.txt
+++ cvs2fossil.txt
@@ -5,58 +5,36 @@
55
* Not yet able to handle the specification of multiple projects
66
for one CVS repository. I.e. I can, for example, import all of
77
tcllib, or a single subproject of tcllib, like tklib, but not
88
multiple sub-projects in one go.
99
10
-* We have to look into the pass 'InitCsets' and hunt for the
11
- cause of the large amount of memory it is gobbling up.
12
-
13
- Results from the first look using the new memory tracking
14
- subsystem:
15
-
16
- (1) The general architecture, workflow, is a bit wasteful. All
17
- changesets are generated and kept in memory before getting
18
- persisted. This means that allocated memory piles up over
19
- time, with later changesets pushing the boundaries. This
20
- is made worse that some of the preliminary changesets seem
21
- to require a lot of temporary memory as part of getting
22
- broken down into the actual ones. InititializeBreakState
23
- seems to be the culprit here. Its memory usage is possibly
24
- quadratic in the number of items in the changeset.
25
-
26
- (2) A number of small inefficiencies. Like 'state eval' always
27
- pulling the whole result into memory before processing it
28
- with 'foreach'. Here potentially large lists.
29
-
30
- (3) We maintain an in-memory map from tagged items to their
31
- changesets. While this is needed later in the sorting
32
- passes during the creation this is wasted space. And also
33
- wasted time, to maintain it during the creation and
34
- breaking.
35
-
36
- Changes:
37
-
38
- (a) Re-architect to create, break, and persist changesets one
39
- by one, completely releasing all associated in-memory data
40
- before going to the next. Should be low-hanging fruit with
41
- high impact, as we have all the necessary operations
42
- already, just not in that order, and that alone should
43
- already keep the pile from forming, making the spikes of
44
- (2) more manageable.
45
-
46
- (b) Look into the smaller problems described in (2), and
47
- especially (3). These should still be low-hanging fruit,
48
- although of lesser effect than (a). For (3) disable the
49
- map and its maintenace during construction, and put it
50
- into a separate command, to be used when loading the
51
- created changesets at the end.
52
-
53
- (c) With larger effect, but more difficult to achieve, go into
54
- command 'InitializeBreakState' and the preceding
55
- 'internalsuccessors', and rearchitect it. Definitely not a
56
- low-hanging fruit. Possibly also something we can skip if
57
- doing (a) had a large enough effect.
10
+* Consider to rework the breaker- and sort-passes so that they
11
+ do not need all changesets as objects in memory.
12
+
13
+ Current memory consumption after all changesets are loaded:
14
+
15
+ bwidget 6971627 6.6
16
+ cvs-memchan 4634049 4.4
17
+ cvs-sqlite 45674501 43.6
18
+ cvs-trf 8781289 8.4
19
+ faqs 2835116 2.7
20
+ libtommath 4405066 4.2
21
+ mclistbox 3350190 3.2
22
+ newclock 5020460 4.8
23
+ oocore 4064574 3.9
24
+ sampleextension 4729932 4.5
25
+ tclapps 8482135 8.1
26
+ tclbench 4116887 3.9
27
+ tcl_bignum 2545192 2.4
28
+ tclconfig 4105042 3.9
29
+ tcllib 31707688 30.2
30
+ tcltutorial 3512048 3.3
31
+ tcl 109926382 104.8
32
+ thread 8953139 8.5
33
+ tklib 13935220 13.3
34
+ tk 66149870 63.1
35
+ widget 2625609 2.5
5836
5937
* Look at the dependencies on external packages and consider
6038
which of them can be moved into the importer, either as a
6139
simple utility command, or wholesale.
6240
6341
--- cvs2fossil.txt
+++ cvs2fossil.txt
@@ -5,58 +5,36 @@
5 * Not yet able to handle the specification of multiple projects
6 for one CVS repository. I.e. I can, for example, import all of
7 tcllib, or a single subproject of tcllib, like tklib, but not
8 multiple sub-projects in one go.
9
10 * We have to look into the pass 'InitCsets' and hunt for the
11 cause of the large amount of memory it is gobbling up.
12
13 Results from the first look using the new memory tracking
14 subsystem:
15
16 (1) The general architecture, workflow, is a bit wasteful. All
17 changesets are generated and kept in memory before getting
18 persisted. This means that allocated memory piles up over
19 time, with later changesets pushing the boundaries. This
20 is made worse that some of the preliminary changesets seem
21 to require a lot of temporary memory as part of getting
22 broken down into the actual ones. InititializeBreakState
23 seems to be the culprit here. Its memory usage is possibly
24 quadratic in the number of items in the changeset.
25
26 (2) A number of small inefficiencies. Like 'state eval' always
27 pulling the whole result into memory before processing it
28 with 'foreach'. Here potentially large lists.
29
30 (3) We maintain an in-memory map from tagged items to their
31 changesets. While this is needed later in the sorting
32 passes during the creation this is wasted space. And also
33 wasted time, to maintain it during the creation and
34 breaking.
35
36 Changes:
37
38 (a) Re-architect to create, break, and persist changesets one
39 by one, completely releasing all associated in-memory data
40 before going to the next. Should be low-hanging fruit with
41 high impact, as we have all the necessary operations
42 already, just not in that order, and that alone should
43 already keep the pile from forming, making the spikes of
44 (2) more manageable.
45
46 (b) Look into the smaller problems described in (2), and
47 especially (3). These should still be low-hanging fruit,
48 although of lesser effect than (a). For (3) disable the
49 map and its maintenace during construction, and put it
50 into a separate command, to be used when loading the
51 created changesets at the end.
52
53 (c) With larger effect, but more difficult to achieve, go into
54 command 'InitializeBreakState' and the preceding
55 'internalsuccessors', and rearchitect it. Definitely not a
56 low-hanging fruit. Possibly also something we can skip if
57 doing (a) had a large enough effect.
58
59 * Look at the dependencies on external packages and consider
60 which of them can be moved into the importer, either as a
61 simple utility command, or wholesale.
62
63
--- cvs2fossil.txt
+++ cvs2fossil.txt
@@ -5,58 +5,36 @@
5 * Not yet able to handle the specification of multiple projects
6 for one CVS repository. I.e. I can, for example, import all of
7 tcllib, or a single subproject of tcllib, like tklib, but not
8 multiple sub-projects in one go.
9
10 * Consider to rework the breaker- and sort-passes so that they
11 do not need all changesets as objects in memory.
12
13 Current memory consumption after all changesets are loaded:
14
15 bwidget 6971627 6.6
16 cvs-memchan 4634049 4.4
17 cvs-sqlite 45674501 43.6
18 cvs-trf 8781289 8.4
19 faqs 2835116 2.7
20 libtommath 4405066 4.2
21 mclistbox 3350190 3.2
22 newclock 5020460 4.8
23 oocore 4064574 3.9
24 sampleextension 4729932 4.5
25 tclapps 8482135 8.1
26 tclbench 4116887 3.9
27 tcl_bignum 2545192 2.4
28 tclconfig 4105042 3.9
29 tcllib 31707688 30.2
30 tcltutorial 3512048 3.3
31 tcl 109926382 104.8
32 thread 8953139 8.5
33 tklib 13935220 13.3
34 tk 66149870 63.1
35 widget 2625609 2.5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
37 * Look at the dependencies on external packages and consider
38 which of them can be moved into the importer, either as a
39 simple utility command, or wholesale.
40
41
--- tools/cvs2fossil/lib/c2f_file.tcl
+++ tools/cvs2fossil/lib/c2f_file.tcl
@@ -314,32 +314,38 @@
314314
315315
set earcs {} ; # Arcs for expansion graph
316316
set zarcs {} ; # Arcs for zip graph
317317
set revmap {} ; # path -> rid map to later merge uuid information
318318
319
- foreach {rid revnr parent child coff clen cid cparent} [state run {
320
- SELECT B.rid, R.rev, R.parent, R.child, B.coff, B.clen, B.bid, B.pid
319
+ state foreachrow {
320
+ SELECT B.rid AS xrid,
321
+ R.rev AS revnr,
322
+ R.child AS xchild,
323
+ B.coff AS xcoff,
324
+ B.clen AS xclen,
325
+ B.bid AS cid,
326
+ B.pid AS cparent
321327
FROM blob B
322328
LEFT OUTER JOIN revision R
323329
ON B.rid = R.rid
324330
WHERE B.fid = $myid
325
- }] {
331
+ } {
326332
# Main data are blobs, most will have revisions, but not
327333
# all. The expansion graph is blob based, whereas the
328334
# recompression graph is revision based.
329335
330336
if {$revnr ne ""} {
331337
# Blob has revision, extend recompression graph.
332338
333
- lappend revmap r$revnr $rid
334
-
335
- $zp node insert $rid
336
- $zp node set $rid revnr $revnr
337
- $zp node set $rid label <$revnr>
338
-
339
- if {$child ne ""} {
340
- lappend zarcs $child $rid
339
+ lappend revmap r$revnr $xrid
340
+
341
+ $zp node insert $xrid
342
+ $zp node set $xrid revnr $revnr
343
+ $zp node set $xrid label <$revnr>
344
+
345
+ if {$xchild ne ""} {
346
+ lappend zarcs $xchild $xrid
341347
}
342348
} else {
343349
# We fake a revnr for the blobs which have no
344350
# revision, for use in the expansion graph.
345351
set revnr ghost$cid
@@ -346,11 +352,11 @@
346352
}
347353
348354
# Now the expansion graph.
349355
350356
$ex node insert $cid
351
- $ex node set $cid text [list $coff $clen]
357
+ $ex node set $cid text [list $xcoff $xclen]
352358
$ex node set $cid revnr $revnr
353359
$ex node set $cid label <$revnr>
354360
355361
if {$cparent ne ""} {
356362
# The expansion arcs go from baseline to delta
357363
--- tools/cvs2fossil/lib/c2f_file.tcl
+++ tools/cvs2fossil/lib/c2f_file.tcl
@@ -314,32 +314,38 @@
314
315 set earcs {} ; # Arcs for expansion graph
316 set zarcs {} ; # Arcs for zip graph
317 set revmap {} ; # path -> rid map to later merge uuid information
318
319 foreach {rid revnr parent child coff clen cid cparent} [state run {
320 SELECT B.rid, R.rev, R.parent, R.child, B.coff, B.clen, B.bid, B.pid
 
 
 
 
 
 
321 FROM blob B
322 LEFT OUTER JOIN revision R
323 ON B.rid = R.rid
324 WHERE B.fid = $myid
325 }] {
326 # Main data are blobs, most will have revisions, but not
327 # all. The expansion graph is blob based, whereas the
328 # recompression graph is revision based.
329
330 if {$revnr ne ""} {
331 # Blob has revision, extend recompression graph.
332
333 lappend revmap r$revnr $rid
334
335 $zp node insert $rid
336 $zp node set $rid revnr $revnr
337 $zp node set $rid label <$revnr>
338
339 if {$child ne ""} {
340 lappend zarcs $child $rid
341 }
342 } else {
343 # We fake a revnr for the blobs which have no
344 # revision, for use in the expansion graph.
345 set revnr ghost$cid
@@ -346,11 +352,11 @@
346 }
347
348 # Now the expansion graph.
349
350 $ex node insert $cid
351 $ex node set $cid text [list $coff $clen]
352 $ex node set $cid revnr $revnr
353 $ex node set $cid label <$revnr>
354
355 if {$cparent ne ""} {
356 # The expansion arcs go from baseline to delta
357
--- tools/cvs2fossil/lib/c2f_file.tcl
+++ tools/cvs2fossil/lib/c2f_file.tcl
@@ -314,32 +314,38 @@
314
315 set earcs {} ; # Arcs for expansion graph
316 set zarcs {} ; # Arcs for zip graph
317 set revmap {} ; # path -> rid map to later merge uuid information
318
319 state foreachrow {
320 SELECT B.rid AS xrid,
321 R.rev AS revnr,
322 R.child AS xchild,
323 B.coff AS xcoff,
324 B.clen AS xclen,
325 B.bid AS cid,
326 B.pid AS cparent
327 FROM blob B
328 LEFT OUTER JOIN revision R
329 ON B.rid = R.rid
330 WHERE B.fid = $myid
331 } {
332 # Main data are blobs, most will have revisions, but not
333 # all. The expansion graph is blob based, whereas the
334 # recompression graph is revision based.
335
336 if {$revnr ne ""} {
337 # Blob has revision, extend recompression graph.
338
339 lappend revmap r$revnr $xrid
340
341 $zp node insert $xrid
342 $zp node set $xrid revnr $revnr
343 $zp node set $xrid label <$revnr>
344
345 if {$xchild ne ""} {
346 lappend zarcs $xchild $xrid
347 }
348 } else {
349 # We fake a revnr for the blobs which have no
350 # revision, for use in the expansion graph.
351 set revnr ghost$cid
@@ -346,11 +352,11 @@
352 }
353
354 # Now the expansion graph.
355
356 $ex node insert $cid
357 $ex node set $cid text [list $xcoff $xclen]
358 $ex node set $cid revnr $revnr
359 $ex node set $cid label <$revnr>
360
361 if {$cparent ne ""} {
362 # The expansion arcs go from baseline to delta
363
--- tools/cvs2fossil/lib/c2f_frev.tcl
+++ tools/cvs2fossil/lib/c2f_frev.tcl
@@ -513,13 +513,13 @@
513513
{1 0} add
514514
{1 1} nothing
515515
}
516516
517517
typemethod getopcodes {} {
518
- foreach {id name} [state run {
518
+ state foreachrow {
519519
SELECT oid, name FROM optype;
520
- }] { set myopcode($name) $id }
520
+ } { set myopcode($name) $oid }
521521
return
522522
}
523523
524524
typevariable myopcode -array {}
525525
526526
--- tools/cvs2fossil/lib/c2f_frev.tcl
+++ tools/cvs2fossil/lib/c2f_frev.tcl
@@ -513,13 +513,13 @@
513 {1 0} add
514 {1 1} nothing
515 }
516
517 typemethod getopcodes {} {
518 foreach {id name} [state run {
519 SELECT oid, name FROM optype;
520 }] { set myopcode($name) $id }
521 return
522 }
523
524 typevariable myopcode -array {}
525
526
--- tools/cvs2fossil/lib/c2f_frev.tcl
+++ tools/cvs2fossil/lib/c2f_frev.tcl
@@ -513,13 +513,13 @@
513 {1 0} add
514 {1 1} nothing
515 }
516
517 typemethod getopcodes {} {
518 state foreachrow {
519 SELECT oid, name FROM optype;
520 } { set myopcode($name) $oid }
521 return
522 }
523
524 typevariable myopcode -array {}
525
526
--- tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
@@ -111,11 +111,13 @@
111111
112112
log write 2 breakacycle {Loading revision commit order}
113113
114114
set n 0
115115
state transaction {
116
- foreach {cid pos} [state run { SELECT cid, pos FROM csorder }] {
116
+ state foreachrow {
117
+ SELECT cid, pos FROM csorder
118
+ } {
117119
log progress 2 breakacycle $n {}
118120
set cset [project::rev of $cid]
119121
$cset setpos $pos
120122
set mycset($pos) $cset
121123
lappend myrevisionchangesets $cset
122124
--- tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
@@ -111,11 +111,13 @@
111
112 log write 2 breakacycle {Loading revision commit order}
113
114 set n 0
115 state transaction {
116 foreach {cid pos} [state run { SELECT cid, pos FROM csorder }] {
 
 
117 log progress 2 breakacycle $n {}
118 set cset [project::rev of $cid]
119 $cset setpos $pos
120 set mycset($pos) $cset
121 lappend myrevisionchangesets $cset
122
--- tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
+++ tools/cvs2fossil/lib/c2f_pbreakacycle.tcl
@@ -111,11 +111,13 @@
111
112 log write 2 breakacycle {Loading revision commit order}
113
114 set n 0
115 state transaction {
116 state foreachrow {
117 SELECT cid, pos FROM csorder
118 } {
119 log progress 2 breakacycle $n {}
120 set cset [project::rev of $cid]
121 $cset setpos $pos
122 set mycset($pos) $cset
123 lappend myrevisionchangesets $cset
124
--- tools/cvs2fossil/lib/c2f_pcollsym.tcl
+++ tools/cvs2fossil/lib/c2f_pcollsym.tcl
@@ -112,24 +112,24 @@
112112
113113
# # ## ### ##### ######## #############
114114
## Internal methods
115115
116116
## TODO: Move UnconvertedSymbols, BadSymbolTypes, BlockedIncludes,
117
- ## InvalidTags to the integrity module?
117
+ ## TODO: InvalidTags to the integrity module?
118118
119119
proc UnconvertedSymbols {} {
120120
# Paranoia - Have we left symbols without conversion
121121
# information (i.e. with type 'undefined') ?
122122
123123
set undef [project::sym undef]
124124
125
- foreach {pname sname} [state run {
126
- SELECT P.name, S.name
125
+ state foreachrow {
126
+ SELECT P.name AS pname, S.name AS sname
127127
FROM symbol S, project P
128128
WHERE S.type = $undef -- Restrict to undefined symbols
129129
AND P.pid = S.pid -- Get project for symbol
130
- }] {
130
+ } {
131131
trouble fatal "$pname : The symbol '$sname' was left undefined"
132132
}
133133
return
134134
}
135135
@@ -136,16 +136,16 @@
136136
proc BadSymbolTypes {} {
137137
# Paranoia - Have we left symbols with bogus conversion
138138
# information (type out of the valid range (excluded, branch,
139139
# tag)) ?
140140
141
- foreach {pname sname} [state run {
142
- SELECT P.name, S.name
141
+ state foreachrow {
142
+ SELECT P.name AS pname, S.name AS sname
143143
FROM symbol S, project P
144144
WHERE S.type NOT IN (0,1,2) -- Restrict to symbols with bogus type codes
145145
AND P.pid = S.pid -- Get project of symbol
146
- }] {
146
+ } {
147147
trouble fatal "$pname : The symbol '$sname' has no proper conversion type"
148148
}
149149
return
150150
}
151151
@@ -153,19 +153,19 @@
153153
# Paranoia - Have we scheduled symbols for exclusion without
154154
# also excluding their dependent symbols ?
155155
156156
set excl [project::sym excluded]
157157
158
- foreach {pname sname bname} [state run {
159
- SELECT P.name, S.name, SB.name
158
+ state foreachrow {
159
+ SELECT P.name AS pname, S.name AS sname, SB.name AS bname
160160
FROM symbol S, blocker B, symbol SB, project P
161161
WHERE S.type = $excl -- Restrict to excluded symbols
162162
AND S.sid = B.sid -- Get symbols blocking them
163163
AND B.bid = SB.sid -- and
164164
AND SB.type != $excl -- which are not excluded themselves
165165
AND P.pid = S.pid -- Get project of symbol
166
- }] {
166
+ } {
167167
trouble fatal "$pname : The symbol '$sname' cannot be excluded as the unexcluded symbol '$bname' depends on it."
168168
}
169169
return
170170
}
171171
@@ -179,17 +179,17 @@
179179
# left to the heuristics, most specifically
180180
# 'project::sym.HasCommits()'.
181181
182182
set tag [project::sym tag]
183183
184
- foreach {pname sname} [state run {
185
- SELECT P.name, S.name
184
+ state foreachrow {
185
+ SELECT P.name AS pname, S.name AS sname
186186
FROM project P, symbol S
187187
WHERE S.type = $tag -- Restrict to tag symbols
188188
AND S.commit_count > 0 -- which have revisions committed to them
189189
AND P.pid = S.pid -- Get project of symbol
190
- }] {
190
+ } {
191191
trouble fatal "$pname : The symbol '$sname' cannot be forced to be converted as tag because it has commits."
192192
}
193193
return
194194
}
195195
@@ -224,12 +224,17 @@
224224
# each candidate overwriting all previous
225225
# selections. Note that we ignore excluded symbol, we
226226
# do not care about their prefered parents and do not
227227
# attempt to compute them.
228228
229
- foreach {s p sname pname prname votes} [state run {
230
- SELECT S.sid, P.pid, S.name, SB.name, PR.name, P.n
229
+ state foreachrow {
230
+ SELECT S.sid AS xs,
231
+ P.pid AS xp,
232
+ S.name AS sname,
233
+ SB.name AS pname,
234
+ PR.name AS prname,
235
+ P.n AS votes
231236
FROM symbol S, parent P, symbol SB, project PR
232237
WHERE S.type != $excl -- Restrict to wanted symbols
233238
AND S.sid = P.sid -- Get possible parents of symbol
234239
AND P.pid = SB.sid -- and
235240
AND S.pid = PR.pid -- the project of the symbol
@@ -238,14 +243,14 @@
238243
-- Higher votes and smaller ids (= earlier branches) last
239244
-- We simply keep the last possible parent for each
240245
-- symbol. This parent will have the max number of votes
241246
-- for its symbol and will be the earliest created branch
242247
-- possible among all with many votes.
243
- }] {
248
+ } {
244249
log write 9 pcollsym "Voting $votes for Parent($sname) = $pname"
245250
246
- set prefered($s) [list $p $sname $pname $prname]
251
+ set prefered($xs) [list $xp $sname $pname $prname]
247252
}
248253
249254
# Phase II: Write the found preferences back into the table
250255
# this pass defined for it.
251256
@@ -262,20 +267,20 @@
262267
# Phase III: Check the result that all symbols except for
263268
# trunks have a prefered parent. We also ignore
264269
# excluded symbols, as we intentionally did not
265270
# compute a prefered parent for them, see phase I.
266271
267
- foreach {pname sname} [state run {
268
- SELECT PR.name, S.name
272
+ state foreachrow {
273
+ SELECT PR.name AS pname, S.name AS sname
269274
FROM symbol S LEFT OUTER JOIN preferedparent P
270275
ON S.sid = P.sid, -- From symbol to prefered parent
271276
project PR
272277
WHERE P.pid IS NULL -- restrict to symbols without a preference
273278
AND S.type != $excl -- which are not excluded
274279
AND S.name != ':trunk:' -- and are not a trunk
275280
AND S.pid = PR.pid -- get project of symbol
276
- }] {
281
+ } {
277282
trouble fatal "$pname : '$sname' has no prefered parent."
278283
}
279284
280285
# The reverse, having prefered parents for unknown symbols
281286
# cannot occur.
282287
--- tools/cvs2fossil/lib/c2f_pcollsym.tcl
+++ tools/cvs2fossil/lib/c2f_pcollsym.tcl
@@ -112,24 +112,24 @@
112
113 # # ## ### ##### ######## #############
114 ## Internal methods
115
116 ## TODO: Move UnconvertedSymbols, BadSymbolTypes, BlockedIncludes,
117 ## InvalidTags to the integrity module?
118
119 proc UnconvertedSymbols {} {
120 # Paranoia - Have we left symbols without conversion
121 # information (i.e. with type 'undefined') ?
122
123 set undef [project::sym undef]
124
125 foreach {pname sname} [state run {
126 SELECT P.name, S.name
127 FROM symbol S, project P
128 WHERE S.type = $undef -- Restrict to undefined symbols
129 AND P.pid = S.pid -- Get project for symbol
130 }] {
131 trouble fatal "$pname : The symbol '$sname' was left undefined"
132 }
133 return
134 }
135
@@ -136,16 +136,16 @@
136 proc BadSymbolTypes {} {
137 # Paranoia - Have we left symbols with bogus conversion
138 # information (type out of the valid range (excluded, branch,
139 # tag)) ?
140
141 foreach {pname sname} [state run {
142 SELECT P.name, S.name
143 FROM symbol S, project P
144 WHERE S.type NOT IN (0,1,2) -- Restrict to symbols with bogus type codes
145 AND P.pid = S.pid -- Get project of symbol
146 }] {
147 trouble fatal "$pname : The symbol '$sname' has no proper conversion type"
148 }
149 return
150 }
151
@@ -153,19 +153,19 @@
153 # Paranoia - Have we scheduled symbols for exclusion without
154 # also excluding their dependent symbols ?
155
156 set excl [project::sym excluded]
157
158 foreach {pname sname bname} [state run {
159 SELECT P.name, S.name, SB.name
160 FROM symbol S, blocker B, symbol SB, project P
161 WHERE S.type = $excl -- Restrict to excluded symbols
162 AND S.sid = B.sid -- Get symbols blocking them
163 AND B.bid = SB.sid -- and
164 AND SB.type != $excl -- which are not excluded themselves
165 AND P.pid = S.pid -- Get project of symbol
166 }] {
167 trouble fatal "$pname : The symbol '$sname' cannot be excluded as the unexcluded symbol '$bname' depends on it."
168 }
169 return
170 }
171
@@ -179,17 +179,17 @@
179 # left to the heuristics, most specifically
180 # 'project::sym.HasCommits()'.
181
182 set tag [project::sym tag]
183
184 foreach {pname sname} [state run {
185 SELECT P.name, S.name
186 FROM project P, symbol S
187 WHERE S.type = $tag -- Restrict to tag symbols
188 AND S.commit_count > 0 -- which have revisions committed to them
189 AND P.pid = S.pid -- Get project of symbol
190 }] {
191 trouble fatal "$pname : The symbol '$sname' cannot be forced to be converted as tag because it has commits."
192 }
193 return
194 }
195
@@ -224,12 +224,17 @@
224 # each candidate overwriting all previous
225 # selections. Note that we ignore excluded symbol, we
226 # do not care about their prefered parents and do not
227 # attempt to compute them.
228
229 foreach {s p sname pname prname votes} [state run {
230 SELECT S.sid, P.pid, S.name, SB.name, PR.name, P.n
 
 
 
 
 
231 FROM symbol S, parent P, symbol SB, project PR
232 WHERE S.type != $excl -- Restrict to wanted symbols
233 AND S.sid = P.sid -- Get possible parents of symbol
234 AND P.pid = SB.sid -- and
235 AND S.pid = PR.pid -- the project of the symbol
@@ -238,14 +243,14 @@
238 -- Higher votes and smaller ids (= earlier branches) last
239 -- We simply keep the last possible parent for each
240 -- symbol. This parent will have the max number of votes
241 -- for its symbol and will be the earliest created branch
242 -- possible among all with many votes.
243 }] {
244 log write 9 pcollsym "Voting $votes for Parent($sname) = $pname"
245
246 set prefered($s) [list $p $sname $pname $prname]
247 }
248
249 # Phase II: Write the found preferences back into the table
250 # this pass defined for it.
251
@@ -262,20 +267,20 @@
262 # Phase III: Check the result that all symbols except for
263 # trunks have a prefered parent. We also ignore
264 # excluded symbols, as we intentionally did not
265 # compute a prefered parent for them, see phase I.
266
267 foreach {pname sname} [state run {
268 SELECT PR.name, S.name
269 FROM symbol S LEFT OUTER JOIN preferedparent P
270 ON S.sid = P.sid, -- From symbol to prefered parent
271 project PR
272 WHERE P.pid IS NULL -- restrict to symbols without a preference
273 AND S.type != $excl -- which are not excluded
274 AND S.name != ':trunk:' -- and are not a trunk
275 AND S.pid = PR.pid -- get project of symbol
276 }] {
277 trouble fatal "$pname : '$sname' has no prefered parent."
278 }
279
280 # The reverse, having prefered parents for unknown symbols
281 # cannot occur.
282
--- tools/cvs2fossil/lib/c2f_pcollsym.tcl
+++ tools/cvs2fossil/lib/c2f_pcollsym.tcl
@@ -112,24 +112,24 @@
112
113 # # ## ### ##### ######## #############
114 ## Internal methods
115
116 ## TODO: Move UnconvertedSymbols, BadSymbolTypes, BlockedIncludes,
117 ## TODO: InvalidTags to the integrity module?
118
119 proc UnconvertedSymbols {} {
120 # Paranoia - Have we left symbols without conversion
121 # information (i.e. with type 'undefined') ?
122
123 set undef [project::sym undef]
124
125 state foreachrow {
126 SELECT P.name AS pname, S.name AS sname
127 FROM symbol S, project P
128 WHERE S.type = $undef -- Restrict to undefined symbols
129 AND P.pid = S.pid -- Get project for symbol
130 } {
131 trouble fatal "$pname : The symbol '$sname' was left undefined"
132 }
133 return
134 }
135
@@ -136,16 +136,16 @@
136 proc BadSymbolTypes {} {
137 # Paranoia - Have we left symbols with bogus conversion
138 # information (type out of the valid range (excluded, branch,
139 # tag)) ?
140
141 state foreachrow {
142 SELECT P.name AS pname, S.name AS sname
143 FROM symbol S, project P
144 WHERE S.type NOT IN (0,1,2) -- Restrict to symbols with bogus type codes
145 AND P.pid = S.pid -- Get project of symbol
146 } {
147 trouble fatal "$pname : The symbol '$sname' has no proper conversion type"
148 }
149 return
150 }
151
@@ -153,19 +153,19 @@
153 # Paranoia - Have we scheduled symbols for exclusion without
154 # also excluding their dependent symbols ?
155
156 set excl [project::sym excluded]
157
158 state foreachrow {
159 SELECT P.name AS pname, S.name AS sname, SB.name AS bname
160 FROM symbol S, blocker B, symbol SB, project P
161 WHERE S.type = $excl -- Restrict to excluded symbols
162 AND S.sid = B.sid -- Get symbols blocking them
163 AND B.bid = SB.sid -- and
164 AND SB.type != $excl -- which are not excluded themselves
165 AND P.pid = S.pid -- Get project of symbol
166 } {
167 trouble fatal "$pname : The symbol '$sname' cannot be excluded as the unexcluded symbol '$bname' depends on it."
168 }
169 return
170 }
171
@@ -179,17 +179,17 @@
179 # left to the heuristics, most specifically
180 # 'project::sym.HasCommits()'.
181
182 set tag [project::sym tag]
183
184 state foreachrow {
185 SELECT P.name AS pname, S.name AS sname
186 FROM project P, symbol S
187 WHERE S.type = $tag -- Restrict to tag symbols
188 AND S.commit_count > 0 -- which have revisions committed to them
189 AND P.pid = S.pid -- Get project of symbol
190 } {
191 trouble fatal "$pname : The symbol '$sname' cannot be forced to be converted as tag because it has commits."
192 }
193 return
194 }
195
@@ -224,12 +224,17 @@
224 # each candidate overwriting all previous
225 # selections. Note that we ignore excluded symbol, we
226 # do not care about their prefered parents and do not
227 # attempt to compute them.
228
229 state foreachrow {
230 SELECT S.sid AS xs,
231 P.pid AS xp,
232 S.name AS sname,
233 SB.name AS pname,
234 PR.name AS prname,
235 P.n AS votes
236 FROM symbol S, parent P, symbol SB, project PR
237 WHERE S.type != $excl -- Restrict to wanted symbols
238 AND S.sid = P.sid -- Get possible parents of symbol
239 AND P.pid = SB.sid -- and
240 AND S.pid = PR.pid -- the project of the symbol
@@ -238,14 +243,14 @@
243 -- Higher votes and smaller ids (= earlier branches) last
244 -- We simply keep the last possible parent for each
245 -- symbol. This parent will have the max number of votes
246 -- for its symbol and will be the earliest created branch
247 -- possible among all with many votes.
248 } {
249 log write 9 pcollsym "Voting $votes for Parent($sname) = $pname"
250
251 set prefered($xs) [list $xp $sname $pname $prname]
252 }
253
254 # Phase II: Write the found preferences back into the table
255 # this pass defined for it.
256
@@ -262,20 +267,20 @@
267 # Phase III: Check the result that all symbols except for
268 # trunks have a prefered parent. We also ignore
269 # excluded symbols, as we intentionally did not
270 # compute a prefered parent for them, see phase I.
271
272 state foreachrow {
273 SELECT PR.name AS pname, S.name AS sname
274 FROM symbol S LEFT OUTER JOIN preferedparent P
275 ON S.sid = P.sid, -- From symbol to prefered parent
276 project PR
277 WHERE P.pid IS NULL -- restrict to symbols without a preference
278 AND S.type != $excl -- which are not excluded
279 AND S.name != ':trunk:' -- and are not a trunk
280 AND S.pid = PR.pid -- get project of symbol
281 } {
282 trouble fatal "$pname : '$sname' has no prefered parent."
283 }
284
285 # The reverse, having prefered parents for unknown symbols
286 # cannot occur.
287
--- tools/cvs2fossil/lib/c2f_pfiltersym.tcl
+++ tools/cvs2fossil/lib/c2f_pfiltersym.tcl
@@ -147,20 +147,22 @@
147147
# links in the database.
148148
149149
array set ntdb {}
150150
array set link {}
151151
152
- foreach {id parent transfer} [state run {
153
- SELECT R.rid, R.parent, R.dbchild
152
+ state foreachrow {
153
+ SELECT R.rid AS xid,
154
+ R.parent AS xparent,
155
+ R.dbchild AS transfer
154156
FROM revision R, symbol S
155157
WHERE R.lod = S.sid -- Get symbol of line-of-development of all revisions
156158
AND S.sid IN excludedsymbols -- Restrict to the excluded symbols
157159
AND R.isdefault -- Restrict to NTDB revisions
158
- }] {
159
- set ntdb($id) $parent
160
+ } {
161
+ set ntdb($xid) $xparent
160162
if {$transfer eq ""} continue
161
- set link($id) $transfer
163
+ set link($xid) $transfer
162164
}
163165
164166
foreach joint [array names link] {
165167
# The joints are the highest NTDB revisions which are
166168
# shared with their respective trunk. We disconnect from
@@ -308,15 +310,15 @@
308310
array set sn [state run { SELECT B.bid, S.name FROM branch B, symbol S WHERE B.sid = S.sid }]
309311
# Symbol names ...
310312
array set sx [state run { SELECT L.sid, L.name FROM symbol L }]
311313
# Files and projects.
312314
array set fpn {}
313
- foreach {id fn pn} [state run {
314
- SELECT F.fid, F.name, P.name
315
+ state foreachrow {
316
+ SELECT F.fid AS id, F.name AS fn, P.name AS pn
315317
FROM file F, project P
316318
WHERE F.pid = P.pid
317
- }] { set fpn($id) [list $fn $pn] }
319
+ } { set fpn($id) [list $fn $pn] }
318320
319321
set tagstoadjust [state run {
320322
SELECT T.tid, T.fid, T.lod, P.pid, S.name, R.rev, R.rid
321323
FROM tag T, preferedparent P, symbol S, revision R
322324
WHERE T.sid = P.sid -- For all tags, get left-hand of prefered parent via symbol
@@ -531,27 +533,35 @@
531533
array set sym {}
532534
set n 0
533535
set t 0
534536
set c 0
535537
536
- foreach {s stype cc p ptype} [state run {
537
- SELECT S.name, A.name, S.commit_count, P.name, B.name
538
+ state foreachrow {
539
+ SELECT S.name AS xs,
540
+ A.name AS stype,
541
+ S.commit_count AS cc,
542
+ P.name AS xp,
543
+ B.name AS ptype
538544
FROM tag T, symbol S, symbol P, symtype A, symtype B
539545
WHERE S.sid = T.sid
540546
AND P.sid = T.lod
541547
AND A.tid = S.type
542548
AND B.tid = P.type
543549
UNION
544
- SELECT S.name, A.name, S.commit_count, P.name, B.name
550
+ SELECT S.name AS xs,
551
+ A.name AS stype,
552
+ S.commit_count AS cc,
553
+ P.name AS xp,
554
+ B.name AS ptype
545555
FROM branch B, symbol S, symbol P, symtype A, symtype B
546556
WHERE S.sid = B.sid
547557
AND P.sid = B.lod
548558
AND A.tid = S.type
549559
AND B.tid = P.type
550
- }] {
551
- lappend sym($s) $p $stype $ptype $cc
552
- maxlen n $s
560
+ } {
561
+ lappend sym($xs) $xp $stype $ptype $cc
562
+ maxlen n $xs
553563
maxlen t $stype
554564
maxlen t $ptype
555565
maxlen c $cc
556566
}
557567
558568
--- tools/cvs2fossil/lib/c2f_pfiltersym.tcl
+++ tools/cvs2fossil/lib/c2f_pfiltersym.tcl
@@ -147,20 +147,22 @@
147 # links in the database.
148
149 array set ntdb {}
150 array set link {}
151
152 foreach {id parent transfer} [state run {
153 SELECT R.rid, R.parent, R.dbchild
 
 
154 FROM revision R, symbol S
155 WHERE R.lod = S.sid -- Get symbol of line-of-development of all revisions
156 AND S.sid IN excludedsymbols -- Restrict to the excluded symbols
157 AND R.isdefault -- Restrict to NTDB revisions
158 }] {
159 set ntdb($id) $parent
160 if {$transfer eq ""} continue
161 set link($id) $transfer
162 }
163
164 foreach joint [array names link] {
165 # The joints are the highest NTDB revisions which are
166 # shared with their respective trunk. We disconnect from
@@ -308,15 +310,15 @@
308 array set sn [state run { SELECT B.bid, S.name FROM branch B, symbol S WHERE B.sid = S.sid }]
309 # Symbol names ...
310 array set sx [state run { SELECT L.sid, L.name FROM symbol L }]
311 # Files and projects.
312 array set fpn {}
313 foreach {id fn pn} [state run {
314 SELECT F.fid, F.name, P.name
315 FROM file F, project P
316 WHERE F.pid = P.pid
317 }] { set fpn($id) [list $fn $pn] }
318
319 set tagstoadjust [state run {
320 SELECT T.tid, T.fid, T.lod, P.pid, S.name, R.rev, R.rid
321 FROM tag T, preferedparent P, symbol S, revision R
322 WHERE T.sid = P.sid -- For all tags, get left-hand of prefered parent via symbol
@@ -531,27 +533,35 @@
531 array set sym {}
532 set n 0
533 set t 0
534 set c 0
535
536 foreach {s stype cc p ptype} [state run {
537 SELECT S.name, A.name, S.commit_count, P.name, B.name
 
 
 
 
538 FROM tag T, symbol S, symbol P, symtype A, symtype B
539 WHERE S.sid = T.sid
540 AND P.sid = T.lod
541 AND A.tid = S.type
542 AND B.tid = P.type
543 UNION
544 SELECT S.name, A.name, S.commit_count, P.name, B.name
 
 
 
 
545 FROM branch B, symbol S, symbol P, symtype A, symtype B
546 WHERE S.sid = B.sid
547 AND P.sid = B.lod
548 AND A.tid = S.type
549 AND B.tid = P.type
550 }] {
551 lappend sym($s) $p $stype $ptype $cc
552 maxlen n $s
553 maxlen t $stype
554 maxlen t $ptype
555 maxlen c $cc
556 }
557
558
--- tools/cvs2fossil/lib/c2f_pfiltersym.tcl
+++ tools/cvs2fossil/lib/c2f_pfiltersym.tcl
@@ -147,20 +147,22 @@
147 # links in the database.
148
149 array set ntdb {}
150 array set link {}
151
152 state foreachrow {
153 SELECT R.rid AS xid,
154 R.parent AS xparent,
155 R.dbchild AS transfer
156 FROM revision R, symbol S
157 WHERE R.lod = S.sid -- Get symbol of line-of-development of all revisions
158 AND S.sid IN excludedsymbols -- Restrict to the excluded symbols
159 AND R.isdefault -- Restrict to NTDB revisions
160 } {
161 set ntdb($xid) $xparent
162 if {$transfer eq ""} continue
163 set link($xid) $transfer
164 }
165
166 foreach joint [array names link] {
167 # The joints are the highest NTDB revisions which are
168 # shared with their respective trunk. We disconnect from
@@ -308,15 +310,15 @@
310 array set sn [state run { SELECT B.bid, S.name FROM branch B, symbol S WHERE B.sid = S.sid }]
311 # Symbol names ...
312 array set sx [state run { SELECT L.sid, L.name FROM symbol L }]
313 # Files and projects.
314 array set fpn {}
315 state foreachrow {
316 SELECT F.fid AS id, F.name AS fn, P.name AS pn
317 FROM file F, project P
318 WHERE F.pid = P.pid
319 } { set fpn($id) [list $fn $pn] }
320
321 set tagstoadjust [state run {
322 SELECT T.tid, T.fid, T.lod, P.pid, S.name, R.rev, R.rid
323 FROM tag T, preferedparent P, symbol S, revision R
324 WHERE T.sid = P.sid -- For all tags, get left-hand of prefered parent via symbol
@@ -531,27 +533,35 @@
533 array set sym {}
534 set n 0
535 set t 0
536 set c 0
537
538 state foreachrow {
539 SELECT S.name AS xs,
540 A.name AS stype,
541 S.commit_count AS cc,
542 P.name AS xp,
543 B.name AS ptype
544 FROM tag T, symbol S, symbol P, symtype A, symtype B
545 WHERE S.sid = T.sid
546 AND P.sid = T.lod
547 AND A.tid = S.type
548 AND B.tid = P.type
549 UNION
550 SELECT S.name AS xs,
551 A.name AS stype,
552 S.commit_count AS cc,
553 P.name AS xp,
554 B.name AS ptype
555 FROM branch B, symbol S, symbol P, symtype A, symtype B
556 WHERE S.sid = B.sid
557 AND P.sid = B.lod
558 AND A.tid = S.type
559 AND B.tid = P.type
560 } {
561 lappend sym($xs) $xp $stype $ptype $cc
562 maxlen n $xs
563 maxlen t $stype
564 maxlen t $ptype
565 maxlen c $cc
566 }
567
568
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -325,18 +325,21 @@
325325
}
326326
327327
proc Getrevisioninfo {revisions} {
328328
set theset ('[join $revisions {','}]')
329329
set revisions {}
330
- #foreachrow
331
- foreach {frid path fname revnr rop} [state run [subst -nocommands -nobackslashes {
332
- SELECT U.uuid, F.visible, F.name, R.rev, R.op
330
+ state foreachrow [subst -nocommands -nobackslashes {
331
+ SELECT U.uuid AS frid,
332
+ F.visible AS path,
333
+ F.name AS fname,
334
+ R.rev AS revnr,
335
+ R.op AS rop
333336
FROM revision R, revuuid U, file F
334337
WHERE R.rid IN $theset -- All specified revisions
335338
AND U.rid = R.rid -- get fossil uuid of revision
336339
AND F.fid = R.fid -- get file of revision
337
- }]] {
340
+ }] {
338341
lappend revisions $frid $path $fname/$revnr $rop
339342
}
340343
return $revisions
341344
}
342345
@@ -584,20 +587,19 @@
584587
# the order given to them by the sort passes. Both the
585588
# filtering by project and sorting make use of 'project::rev
586589
# rev' impossible.
587590
588591
set res {}
589
- #foreachrow
590
- foreach {cid cdate} [state run {
591
- SELECT C.cid, T.date
592
+ state foreachrow {
593
+ SELECT C.cid AS xcid, T.date AS cdate
592594
FROM changeset C, cstimestamp T
593595
WHERE C.type = 0 -- limit to revision changesets
594596
AND C.pid = $projectid -- limit to changesets in project
595597
AND T.cid = C.cid -- get ordering information
596598
ORDER BY T.date -- sort into commit order
597
- }] {
598
- lappend res $myidmap($cid) $cdate
599
+ } {
600
+ lappend res $myidmap($xcid) $cdate
599601
}
600602
return $res
601603
}
602604
603605
typemethod getcstypes {} {
@@ -899,17 +901,16 @@
899901
900902
array set delta {}
901903
array set stamp {}
902904
903905
set theset ('[join $revisions {','}]')
904
- #foreachrow
905
- foreach {rid time} [state run [subst -nocommands -nobackslashes {
906
- SELECT R.rid, R.date
906
+ state foreachrow [subst -nocommands -nobackslashes {
907
+ SELECT R.rid AS xrid, R.date AS time
907908
FROM revision R
908909
WHERE R.rid IN $theset
909
- }]] {
910
- set stamp($rid) $time
910
+ }] {
911
+ set stamp($xrid) $time
911912
}
912913
913914
log write 14 csets {IBS: stamp [array size stamp]}
914915
915916
set n 0
@@ -1326,54 +1327,51 @@
13261327
# '1.2' revision) is a successor, if it exists.
13271328
13281329
# Note that the branches spawned from the revisions, and the
13291330
# tags associated with them are successors as well.
13301331
1331
- #foreachrow
1332
- foreach {rid child} [state run [subst -nocommands -nobackslashes {
1332
+ state foreachrow [subst -nocommands -nobackslashes {
13331333
-- (1) Primary child
1334
- SELECT R.rid, R.child
1334
+ SELECT R.rid AS xrid, R.child AS xchild
13351335
FROM revision R
13361336
WHERE R.rid IN $theset -- Restrict to revisions of interest
13371337
AND R.child IS NOT NULL -- Has primary child
13381338
UNION
13391339
-- (2) Secondary (branch) children
1340
- SELECT R.rid, B.brid
1340
+ SELECT R.rid AS xrid, B.brid AS xchild
13411341
FROM revision R, revisionbranchchildren B
13421342
WHERE R.rid IN $theset -- Restrict to revisions of interest
13431343
AND R.rid = B.rid -- Select subset of branch children
13441344
UNION
13451345
-- (4) Child of trunk root successor of last NTDB on trunk.
1346
- SELECT R.rid, RA.child
1346
+ SELECT R.rid AS xrid, RA.child AS xchild
13471347
FROM revision R, revision RA
13481348
WHERE R.rid IN $theset -- Restrict to revisions of interest
13491349
AND R.isdefault -- Restrict to NTDB
13501350
AND R.dbchild IS NOT NULL -- and last NTDB belonging to trunk
13511351
AND RA.rid = R.dbchild -- Go directly to trunk root
13521352
AND RA.child IS NOT NULL -- Has primary child.
1353
- }]] {
1353
+ }] {
13541354
# Consider moving this to the integrity module.
1355
- integrity assert {$rid != $child} {Revision $rid depends on itself.}
1356
- lappend dependencies([list rev $rid]) [list rev $child]
1355
+ integrity assert {$xrid != $xchild} {Revision $xrid depends on itself.}
1356
+ lappend dependencies([list rev $xrid]) [list rev $xchild]
13571357
}
1358
- #foreachrow
1359
- foreach {rid child} [state run [subst -nocommands -nobackslashes {
1360
- SELECT R.rid, T.tid
1358
+ state foreachrow [subst -nocommands -nobackslashes {
1359
+ SELECT R.rid AS xrid, T.tid AS xchild
13611360
FROM revision R, tag T
13621361
WHERE R.rid IN $theset -- Restrict to revisions of interest
13631362
AND T.rev = R.rid -- Select tags attached to them
1364
- }]] {
1365
- lappend dependencies([list rev $rid]) [list sym::tag $child]
1363
+ }] {
1364
+ lappend dependencies([list rev $xrid]) [list sym::tag $xchild]
13661365
}
1367
- #foreachrow
1368
- foreach {rid child} [state run [subst -nocommands -nobackslashes {
1369
- SELECT R.rid, B.bid
1366
+ state foreachrow [subst -nocommands -nobackslashes {
1367
+ SELECT R.rid AS xrid, B.bid AS xchild
13701368
FROM revision R, branch B
13711369
WHERE R.rid IN $theset -- Restrict to revisions of interest
13721370
AND B.root = R.rid -- Select branches attached to them
1373
- }]] {
1374
- lappend dependencies([list rev $rid]) [list sym::branch $child]
1371
+ }] {
1372
+ lappend dependencies([list rev $xrid]) [list sym::branch $xchild]
13751373
}
13761374
return
13771375
}
13781376
13791377
# result = list (changeset-id)
@@ -1581,38 +1579,35 @@
15811579
# The first revision committed on a branch, and all branches
15821580
# and tags which have it as their prefered parent are the
15831581
# successors of a branch.
15841582
15851583
set theset ('[join $branches {','}]')
1586
- #foreachrow
1587
- foreach {bid child} [state run [subst -nocommands -nobackslashes {
1588
- SELECT B.bid, R.rid
1584
+ state foreachrow [subst -nocommands -nobackslashes {
1585
+ SELECT B.bid AS xbid, R.rid AS xchild
15891586
FROM branch B, revision R
15901587
WHERE B.bid IN $theset -- Restrict to branches of interest
15911588
AND B.first = R.rid -- Get first revision on the branch
1592
- }]] {
1593
- lappend dependencies([list sym::branch $bid]) [list rev $child]
1589
+ }] {
1590
+ lappend dependencies([list sym::branch $xbid]) [list rev $xchild]
15941591
}
1595
- #foreachrow
1596
- foreach {bid child} [state run [subst -nocommands -nobackslashes {
1597
- SELECT B.bid, BX.bid
1592
+ state foreachrow [subst -nocommands -nobackslashes {
1593
+ SELECT B.bid AS xbid, BX.bid AS xchild
15981594
FROM branch B, preferedparent P, branch BX
15991595
WHERE B.bid IN $theset -- Restrict to branches of interest
16001596
AND B.sid = P.pid -- Get subordinate branches via the
16011597
AND BX.sid = P.sid -- prefered parents of their symbols
1602
- }]] {
1603
- lappend dependencies([list sym::branch $bid]) [list sym::branch $child]
1598
+ }] {
1599
+ lappend dependencies([list sym::branch $xbid]) [list sym::branch $xchild]
16041600
}
1605
- #foreachrow
1606
- foreach {bid child} [state run [subst -nocommands -nobackslashes {
1607
- SELECT B.bid, T.tid
1601
+ state foreachrow [subst -nocommands -nobackslashes {
1602
+ SELECT B.bid AS xbid, T.tid AS xchild
16081603
FROM branch B, preferedparent P, tag T
16091604
WHERE B.bid IN $theset -- Restrict to branches of interest
16101605
AND B.sid = P.pid -- Get subordinate tags via the
16111606
AND T.sid = P.sid -- prefered parents of their symbols
1612
- }]] {
1613
- lappend dependencies([list sym::branch $bid]) [list sym::tag $child]
1607
+ }] {
1608
+ lappend dependencies([list sym::branch $xbid]) [list sym::tag $xchild]
16141609
}
16151610
return
16161611
}
16171612
16181613
# result = list (changeset-id)
16191614
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -325,18 +325,21 @@
325 }
326
327 proc Getrevisioninfo {revisions} {
328 set theset ('[join $revisions {','}]')
329 set revisions {}
330 #foreachrow
331 foreach {frid path fname revnr rop} [state run [subst -nocommands -nobackslashes {
332 SELECT U.uuid, F.visible, F.name, R.rev, R.op
 
 
 
333 FROM revision R, revuuid U, file F
334 WHERE R.rid IN $theset -- All specified revisions
335 AND U.rid = R.rid -- get fossil uuid of revision
336 AND F.fid = R.fid -- get file of revision
337 }]] {
338 lappend revisions $frid $path $fname/$revnr $rop
339 }
340 return $revisions
341 }
342
@@ -584,20 +587,19 @@
584 # the order given to them by the sort passes. Both the
585 # filtering by project and sorting make use of 'project::rev
586 # rev' impossible.
587
588 set res {}
589 #foreachrow
590 foreach {cid cdate} [state run {
591 SELECT C.cid, T.date
592 FROM changeset C, cstimestamp T
593 WHERE C.type = 0 -- limit to revision changesets
594 AND C.pid = $projectid -- limit to changesets in project
595 AND T.cid = C.cid -- get ordering information
596 ORDER BY T.date -- sort into commit order
597 }] {
598 lappend res $myidmap($cid) $cdate
599 }
600 return $res
601 }
602
603 typemethod getcstypes {} {
@@ -899,17 +901,16 @@
899
900 array set delta {}
901 array set stamp {}
902
903 set theset ('[join $revisions {','}]')
904 #foreachrow
905 foreach {rid time} [state run [subst -nocommands -nobackslashes {
906 SELECT R.rid, R.date
907 FROM revision R
908 WHERE R.rid IN $theset
909 }]] {
910 set stamp($rid) $time
911 }
912
913 log write 14 csets {IBS: stamp [array size stamp]}
914
915 set n 0
@@ -1326,54 +1327,51 @@
1326 # '1.2' revision) is a successor, if it exists.
1327
1328 # Note that the branches spawned from the revisions, and the
1329 # tags associated with them are successors as well.
1330
1331 #foreachrow
1332 foreach {rid child} [state run [subst -nocommands -nobackslashes {
1333 -- (1) Primary child
1334 SELECT R.rid, R.child
1335 FROM revision R
1336 WHERE R.rid IN $theset -- Restrict to revisions of interest
1337 AND R.child IS NOT NULL -- Has primary child
1338 UNION
1339 -- (2) Secondary (branch) children
1340 SELECT R.rid, B.brid
1341 FROM revision R, revisionbranchchildren B
1342 WHERE R.rid IN $theset -- Restrict to revisions of interest
1343 AND R.rid = B.rid -- Select subset of branch children
1344 UNION
1345 -- (4) Child of trunk root successor of last NTDB on trunk.
1346 SELECT R.rid, RA.child
1347 FROM revision R, revision RA
1348 WHERE R.rid IN $theset -- Restrict to revisions of interest
1349 AND R.isdefault -- Restrict to NTDB
1350 AND R.dbchild IS NOT NULL -- and last NTDB belonging to trunk
1351 AND RA.rid = R.dbchild -- Go directly to trunk root
1352 AND RA.child IS NOT NULL -- Has primary child.
1353 }]] {
1354 # Consider moving this to the integrity module.
1355 integrity assert {$rid != $child} {Revision $rid depends on itself.}
1356 lappend dependencies([list rev $rid]) [list rev $child]
1357 }
1358 #foreachrow
1359 foreach {rid child} [state run [subst -nocommands -nobackslashes {
1360 SELECT R.rid, T.tid
1361 FROM revision R, tag T
1362 WHERE R.rid IN $theset -- Restrict to revisions of interest
1363 AND T.rev = R.rid -- Select tags attached to them
1364 }]] {
1365 lappend dependencies([list rev $rid]) [list sym::tag $child]
1366 }
1367 #foreachrow
1368 foreach {rid child} [state run [subst -nocommands -nobackslashes {
1369 SELECT R.rid, B.bid
1370 FROM revision R, branch B
1371 WHERE R.rid IN $theset -- Restrict to revisions of interest
1372 AND B.root = R.rid -- Select branches attached to them
1373 }]] {
1374 lappend dependencies([list rev $rid]) [list sym::branch $child]
1375 }
1376 return
1377 }
1378
1379 # result = list (changeset-id)
@@ -1581,38 +1579,35 @@
1581 # The first revision committed on a branch, and all branches
1582 # and tags which have it as their prefered parent are the
1583 # successors of a branch.
1584
1585 set theset ('[join $branches {','}]')
1586 #foreachrow
1587 foreach {bid child} [state run [subst -nocommands -nobackslashes {
1588 SELECT B.bid, R.rid
1589 FROM branch B, revision R
1590 WHERE B.bid IN $theset -- Restrict to branches of interest
1591 AND B.first = R.rid -- Get first revision on the branch
1592 }]] {
1593 lappend dependencies([list sym::branch $bid]) [list rev $child]
1594 }
1595 #foreachrow
1596 foreach {bid child} [state run [subst -nocommands -nobackslashes {
1597 SELECT B.bid, BX.bid
1598 FROM branch B, preferedparent P, branch BX
1599 WHERE B.bid IN $theset -- Restrict to branches of interest
1600 AND B.sid = P.pid -- Get subordinate branches via the
1601 AND BX.sid = P.sid -- prefered parents of their symbols
1602 }]] {
1603 lappend dependencies([list sym::branch $bid]) [list sym::branch $child]
1604 }
1605 #foreachrow
1606 foreach {bid child} [state run [subst -nocommands -nobackslashes {
1607 SELECT B.bid, T.tid
1608 FROM branch B, preferedparent P, tag T
1609 WHERE B.bid IN $theset -- Restrict to branches of interest
1610 AND B.sid = P.pid -- Get subordinate tags via the
1611 AND T.sid = P.sid -- prefered parents of their symbols
1612 }]] {
1613 lappend dependencies([list sym::branch $bid]) [list sym::tag $child]
1614 }
1615 return
1616 }
1617
1618 # result = list (changeset-id)
1619
--- tools/cvs2fossil/lib/c2f_prev.tcl
+++ tools/cvs2fossil/lib/c2f_prev.tcl
@@ -325,18 +325,21 @@
325 }
326
327 proc Getrevisioninfo {revisions} {
328 set theset ('[join $revisions {','}]')
329 set revisions {}
330 state foreachrow [subst -nocommands -nobackslashes {
331 SELECT U.uuid AS frid,
332 F.visible AS path,
333 F.name AS fname,
334 R.rev AS revnr,
335 R.op AS rop
336 FROM revision R, revuuid U, file F
337 WHERE R.rid IN $theset -- All specified revisions
338 AND U.rid = R.rid -- get fossil uuid of revision
339 AND F.fid = R.fid -- get file of revision
340 }] {
341 lappend revisions $frid $path $fname/$revnr $rop
342 }
343 return $revisions
344 }
345
@@ -584,20 +587,19 @@
587 # the order given to them by the sort passes. Both the
588 # filtering by project and sorting make use of 'project::rev
589 # rev' impossible.
590
591 set res {}
592 state foreachrow {
593 SELECT C.cid AS xcid, T.date AS cdate
 
594 FROM changeset C, cstimestamp T
595 WHERE C.type = 0 -- limit to revision changesets
596 AND C.pid = $projectid -- limit to changesets in project
597 AND T.cid = C.cid -- get ordering information
598 ORDER BY T.date -- sort into commit order
599 } {
600 lappend res $myidmap($xcid) $cdate
601 }
602 return $res
603 }
604
605 typemethod getcstypes {} {
@@ -899,17 +901,16 @@
901
902 array set delta {}
903 array set stamp {}
904
905 set theset ('[join $revisions {','}]')
906 state foreachrow [subst -nocommands -nobackslashes {
907 SELECT R.rid AS xrid, R.date AS time
 
908 FROM revision R
909 WHERE R.rid IN $theset
910 }] {
911 set stamp($xrid) $time
912 }
913
914 log write 14 csets {IBS: stamp [array size stamp]}
915
916 set n 0
@@ -1326,54 +1327,51 @@
1327 # '1.2' revision) is a successor, if it exists.
1328
1329 # Note that the branches spawned from the revisions, and the
1330 # tags associated with them are successors as well.
1331
1332 state foreachrow [subst -nocommands -nobackslashes {
 
1333 -- (1) Primary child
1334 SELECT R.rid AS xrid, R.child AS xchild
1335 FROM revision R
1336 WHERE R.rid IN $theset -- Restrict to revisions of interest
1337 AND R.child IS NOT NULL -- Has primary child
1338 UNION
1339 -- (2) Secondary (branch) children
1340 SELECT R.rid AS xrid, B.brid AS xchild
1341 FROM revision R, revisionbranchchildren B
1342 WHERE R.rid IN $theset -- Restrict to revisions of interest
1343 AND R.rid = B.rid -- Select subset of branch children
1344 UNION
1345 -- (4) Child of trunk root successor of last NTDB on trunk.
1346 SELECT R.rid AS xrid, RA.child AS xchild
1347 FROM revision R, revision RA
1348 WHERE R.rid IN $theset -- Restrict to revisions of interest
1349 AND R.isdefault -- Restrict to NTDB
1350 AND R.dbchild IS NOT NULL -- and last NTDB belonging to trunk
1351 AND RA.rid = R.dbchild -- Go directly to trunk root
1352 AND RA.child IS NOT NULL -- Has primary child.
1353 }] {
1354 # Consider moving this to the integrity module.
1355 integrity assert {$xrid != $xchild} {Revision $xrid depends on itself.}
1356 lappend dependencies([list rev $xrid]) [list rev $xchild]
1357 }
1358 state foreachrow [subst -nocommands -nobackslashes {
1359 SELECT R.rid AS xrid, T.tid AS xchild
 
1360 FROM revision R, tag T
1361 WHERE R.rid IN $theset -- Restrict to revisions of interest
1362 AND T.rev = R.rid -- Select tags attached to them
1363 }] {
1364 lappend dependencies([list rev $xrid]) [list sym::tag $xchild]
1365 }
1366 state foreachrow [subst -nocommands -nobackslashes {
1367 SELECT R.rid AS xrid, B.bid AS xchild
 
1368 FROM revision R, branch B
1369 WHERE R.rid IN $theset -- Restrict to revisions of interest
1370 AND B.root = R.rid -- Select branches attached to them
1371 }] {
1372 lappend dependencies([list rev $xrid]) [list sym::branch $xchild]
1373 }
1374 return
1375 }
1376
1377 # result = list (changeset-id)
@@ -1581,38 +1579,35 @@
1579 # The first revision committed on a branch, and all branches
1580 # and tags which have it as their prefered parent are the
1581 # successors of a branch.
1582
1583 set theset ('[join $branches {','}]')
1584 state foreachrow [subst -nocommands -nobackslashes {
1585 SELECT B.bid AS xbid, R.rid AS xchild
 
1586 FROM branch B, revision R
1587 WHERE B.bid IN $theset -- Restrict to branches of interest
1588 AND B.first = R.rid -- Get first revision on the branch
1589 }] {
1590 lappend dependencies([list sym::branch $xbid]) [list rev $xchild]
1591 }
1592 state foreachrow [subst -nocommands -nobackslashes {
1593 SELECT B.bid AS xbid, BX.bid AS xchild
 
1594 FROM branch B, preferedparent P, branch BX
1595 WHERE B.bid IN $theset -- Restrict to branches of interest
1596 AND B.sid = P.pid -- Get subordinate branches via the
1597 AND BX.sid = P.sid -- prefered parents of their symbols
1598 }] {
1599 lappend dependencies([list sym::branch $xbid]) [list sym::branch $xchild]
1600 }
1601 state foreachrow [subst -nocommands -nobackslashes {
1602 SELECT B.bid AS xbid, T.tid AS xchild
 
1603 FROM branch B, preferedparent P, tag T
1604 WHERE B.bid IN $theset -- Restrict to branches of interest
1605 AND B.sid = P.pid -- Get subordinate tags via the
1606 AND T.sid = P.sid -- prefered parents of their symbols
1607 }] {
1608 lappend dependencies([list sym::branch $xbid]) [list sym::tag $xchild]
1609 }
1610 return
1611 }
1612
1613 # result = list (changeset-id)
1614
--- tools/cvs2fossil/lib/c2f_psym.tcl
+++ tools/cvs2fossil/lib/c2f_psym.tcl
@@ -249,13 +249,13 @@
249249
typevariable myforcepattern {} ; # List of patterns and types
250250
# specifying which symbols to
251251
# force to specific types.
252252
253253
typemethod getsymtypes {} {
254
- foreach {tid name} [state run {
254
+ state foreachrow {
255255
SELECT tid, name FROM symtype;
256
- }] { set mysymtype($tid) $name }
256
+ } { set mysymtype($tid) $name }
257257
return
258258
}
259259
260260
# Keep the codes below in sync with 'pass::collrev/setup('symtype').
261261
typevariable myexcluded 0 ; # Code for symbols which are excluded.
@@ -299,18 +299,19 @@
299299
log write 2 symbol "Symbol type statistics:"
300300
301301
set fmt %[string length $mynum]s
302302
set all 0
303303
304
- foreach {stype splural n} [state run {
305
- SELECT T.name, T.plural, COUNT (s.sid)
304
+ state foreachrow {
305
+ SELECT T.name AS stype,
306
+ T.plural AS splural,
307
+ COUNT (s.sid) AS n
306308
FROM symbol S, symtype T
307309
WHERE S.type = T.tid
308310
GROUP BY T.name
309311
ORDER BY T.name
310
- ;
311
- }] {
312
+ } {
312313
log write 2 symbol "* [format $fmt $n] [sp $n $stype $splural]"
313314
incr all $n
314315
}
315316
316317
log write 2 symbol "= [format $fmt $all] total"
@@ -391,13 +392,12 @@
391392
incr myrulecount($label)
392393
393394
# This is stored directly into the database.
394395
state run {
395396
UPDATE symbol
396
- SET type = $chosen
397
- WHERE sid = $myid
398
- ;
397
+ SET type = $chosen
398
+ WHERE sid = $myid
399399
}
400400
return
401401
}
402402
403403
# # ## ### ##### ######## #############
404404
--- tools/cvs2fossil/lib/c2f_psym.tcl
+++ tools/cvs2fossil/lib/c2f_psym.tcl
@@ -249,13 +249,13 @@
249 typevariable myforcepattern {} ; # List of patterns and types
250 # specifying which symbols to
251 # force to specific types.
252
253 typemethod getsymtypes {} {
254 foreach {tid name} [state run {
255 SELECT tid, name FROM symtype;
256 }] { set mysymtype($tid) $name }
257 return
258 }
259
260 # Keep the codes below in sync with 'pass::collrev/setup('symtype').
261 typevariable myexcluded 0 ; # Code for symbols which are excluded.
@@ -299,18 +299,19 @@
299 log write 2 symbol "Symbol type statistics:"
300
301 set fmt %[string length $mynum]s
302 set all 0
303
304 foreach {stype splural n} [state run {
305 SELECT T.name, T.plural, COUNT (s.sid)
 
 
306 FROM symbol S, symtype T
307 WHERE S.type = T.tid
308 GROUP BY T.name
309 ORDER BY T.name
310 ;
311 }] {
312 log write 2 symbol "* [format $fmt $n] [sp $n $stype $splural]"
313 incr all $n
314 }
315
316 log write 2 symbol "= [format $fmt $all] total"
@@ -391,13 +392,12 @@
391 incr myrulecount($label)
392
393 # This is stored directly into the database.
394 state run {
395 UPDATE symbol
396 SET type = $chosen
397 WHERE sid = $myid
398 ;
399 }
400 return
401 }
402
403 # # ## ### ##### ######## #############
404
--- tools/cvs2fossil/lib/c2f_psym.tcl
+++ tools/cvs2fossil/lib/c2f_psym.tcl
@@ -249,13 +249,13 @@
249 typevariable myforcepattern {} ; # List of patterns and types
250 # specifying which symbols to
251 # force to specific types.
252
253 typemethod getsymtypes {} {
254 state foreachrow {
255 SELECT tid, name FROM symtype;
256 } { set mysymtype($tid) $name }
257 return
258 }
259
260 # Keep the codes below in sync with 'pass::collrev/setup('symtype').
261 typevariable myexcluded 0 ; # Code for symbols which are excluded.
@@ -299,18 +299,19 @@
299 log write 2 symbol "Symbol type statistics:"
300
301 set fmt %[string length $mynum]s
302 set all 0
303
304 state foreachrow {
305 SELECT T.name AS stype,
306 T.plural AS splural,
307 COUNT (s.sid) AS n
308 FROM symbol S, symtype T
309 WHERE S.type = T.tid
310 GROUP BY T.name
311 ORDER BY T.name
312 } {
 
313 log write 2 symbol "* [format $fmt $n] [sp $n $stype $splural]"
314 incr all $n
315 }
316
317 log write 2 symbol "= [format $fmt $all] total"
@@ -391,13 +392,12 @@
392 incr myrulecount($label)
393
394 # This is stored directly into the database.
395 state run {
396 UPDATE symbol
397 SET type = $chosen
398 WHERE sid = $myid
 
399 }
400 return
401 }
402
403 # # ## ### ##### ######## #############
404
--- tools/cvs2fossil/lib/c2f_repository.tcl
+++ tools/cvs2fossil/lib/c2f_repository.tcl
@@ -152,23 +152,23 @@
152152
return
153153
}
154154
155155
typemethod load {} {
156156
state transaction {
157
- foreach {pid name} [state run {
157
+ state foreachrow {
158158
SELECT pid, name FROM project ;
159
- }] {
159
+ } {
160160
set project [project %AUTO% $name $type]
161161
162162
lappend myprojpaths $name
163163
lappend myprojects $project
164164
set myprojmap($pid) $project
165165
$project setid $pid
166166
}
167
- foreach {fid pid name visible exec} [state run {
167
+ state foreachrow {
168168
SELECT fid, pid, name, visible, exec FROM file ;
169
- }] {
169
+ } {
170170
$myprojmap($pid) addfile $name $visible $exec $fid
171171
}
172172
}
173173
return
174174
}
@@ -244,15 +244,14 @@
244244
typemethod loadsymbols {} {
245245
state transaction {
246246
# We load the symbol ids at large to have the mapping
247247
# right from the beginning.
248248
249
- foreach {sid pid name tc bc cc} [state run {
250
- SELECT sid, pid, name, tag_count, branch_count, commit_count
249
+ state foreachrow {
250
+ SELECT sid, pid, name, tag_count AS tc, branch_count AS bc, commit_count AS cc
251251
FROM symbol
252
- ;
253
- }] {
252
+ } {
254253
$mysymbol map $sid [list $pid $name]
255254
set project $myprojmap($pid)
256255
257256
set force [$project hassymbol $name]
258257
set symbol [$project getsymbol $name]
@@ -271,23 +270,23 @@
271270
}
272271
273272
# Beyond the symbols we also load the author, commit log,
274273
# and meta information.
275274
276
- foreach {aid aname} [state run {
277
- SELECT aid, name FROM author
278
- }] {
275
+ state foreachrow {
276
+ SELECT aid, name AS aname FROM author
277
+ } {
279278
$myauthor map $aid $aname
280279
}
281
- foreach {cid text} [state run {
280
+ state foreachrow {
282281
SELECT cid, text FROM cmessage
283
- }] {
282
+ } {
284283
$mycmsg map $cid $text
285284
}
286
- foreach {mid pid bid aid cid} [state run {
285
+ state foreachrow {
287286
SELECT mid, pid, bid, aid, cid FROM meta
288
- }] {
287
+ } {
289288
$mymeta map $mid [list $pid $bid $aid $cid]
290289
}
291290
}
292291
return
293292
}
294293
--- tools/cvs2fossil/lib/c2f_repository.tcl
+++ tools/cvs2fossil/lib/c2f_repository.tcl
@@ -152,23 +152,23 @@
152 return
153 }
154
155 typemethod load {} {
156 state transaction {
157 foreach {pid name} [state run {
158 SELECT pid, name FROM project ;
159 }] {
160 set project [project %AUTO% $name $type]
161
162 lappend myprojpaths $name
163 lappend myprojects $project
164 set myprojmap($pid) $project
165 $project setid $pid
166 }
167 foreach {fid pid name visible exec} [state run {
168 SELECT fid, pid, name, visible, exec FROM file ;
169 }] {
170 $myprojmap($pid) addfile $name $visible $exec $fid
171 }
172 }
173 return
174 }
@@ -244,15 +244,14 @@
244 typemethod loadsymbols {} {
245 state transaction {
246 # We load the symbol ids at large to have the mapping
247 # right from the beginning.
248
249 foreach {sid pid name tc bc cc} [state run {
250 SELECT sid, pid, name, tag_count, branch_count, commit_count
251 FROM symbol
252 ;
253 }] {
254 $mysymbol map $sid [list $pid $name]
255 set project $myprojmap($pid)
256
257 set force [$project hassymbol $name]
258 set symbol [$project getsymbol $name]
@@ -271,23 +270,23 @@
271 }
272
273 # Beyond the symbols we also load the author, commit log,
274 # and meta information.
275
276 foreach {aid aname} [state run {
277 SELECT aid, name FROM author
278 }] {
279 $myauthor map $aid $aname
280 }
281 foreach {cid text} [state run {
282 SELECT cid, text FROM cmessage
283 }] {
284 $mycmsg map $cid $text
285 }
286 foreach {mid pid bid aid cid} [state run {
287 SELECT mid, pid, bid, aid, cid FROM meta
288 }] {
289 $mymeta map $mid [list $pid $bid $aid $cid]
290 }
291 }
292 return
293 }
294
--- tools/cvs2fossil/lib/c2f_repository.tcl
+++ tools/cvs2fossil/lib/c2f_repository.tcl
@@ -152,23 +152,23 @@
152 return
153 }
154
155 typemethod load {} {
156 state transaction {
157 state foreachrow {
158 SELECT pid, name FROM project ;
159 } {
160 set project [project %AUTO% $name $type]
161
162 lappend myprojpaths $name
163 lappend myprojects $project
164 set myprojmap($pid) $project
165 $project setid $pid
166 }
167 state foreachrow {
168 SELECT fid, pid, name, visible, exec FROM file ;
169 } {
170 $myprojmap($pid) addfile $name $visible $exec $fid
171 }
172 }
173 return
174 }
@@ -244,15 +244,14 @@
244 typemethod loadsymbols {} {
245 state transaction {
246 # We load the symbol ids at large to have the mapping
247 # right from the beginning.
248
249 state foreachrow {
250 SELECT sid, pid, name, tag_count AS tc, branch_count AS bc, commit_count AS cc
251 FROM symbol
252 } {
 
253 $mysymbol map $sid [list $pid $name]
254 set project $myprojmap($pid)
255
256 set force [$project hassymbol $name]
257 set symbol [$project getsymbol $name]
@@ -271,23 +270,23 @@
270 }
271
272 # Beyond the symbols we also load the author, commit log,
273 # and meta information.
274
275 state foreachrow {
276 SELECT aid, name AS aname FROM author
277 } {
278 $myauthor map $aid $aname
279 }
280 state foreachrow {
281 SELECT cid, text FROM cmessage
282 } {
283 $mycmsg map $cid $text
284 }
285 state foreachrow {
286 SELECT mid, pid, bid, aid, cid FROM meta
287 } {
288 $mymeta map $mid [list $pid $bid $aid $cid]
289 }
290 }
291 return
292 }
293

Keyboard Shortcuts

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