Fossil

Check-in [f637d422]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Updated my notes regarding memory usage. Converted more locations to incremental query processing via 'state foreachrow', now throughout the importer.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f637d4220695430e25040509f12f050d2f4cd42f
User & Date: aku 2008-02-24 18:01:40
Context
2008-02-24
18:50
Merged to [ed26056bb5]. check-in: 588bb7cd user: aku tags: trunk
18:01
Updated my notes regarding memory usage. Converted more locations to incremental query processing via 'state foreachrow', now throughout the importer. check-in: f637d422 user: aku tags: trunk
04:43
New command 'state foreachrow' for incremental result processing, using less memory. Converted a number of places in pass InitCSet to this command, and marked a number of othre places for possible future use. check-in: 6559f323 user: aku tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to cvs2fossil.txt.

3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22
23
24
25

26
27
28
29

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
===================================

*	Not yet able to handle the specification of multiple projects
	for one CVS repository. I.e. I can, for example, import all of
	tcllib, or a single subproject of tcllib, like tklib, but not
	multiple sub-projects in one go.

*	We have to look into the pass 'InitCsets' and hunt for the
	cause of the large amount of memory it is gobbling up.

	Results from the first look using the new memory tracking
	subsystem:


	(1) The general architecture, workflow, is a bit wasteful. All
	    changesets are generated and kept in memory before getting
	    persisted. This means that allocated memory piles up over
	    time, with later changesets pushing the boundaries. This
	    is made worse that some of the preliminary changesets seem
	    to require a lot of temporary memory as part of getting
	    broken down into the actual ones. InititializeBreakState
	    seems to be the culprit here. Its memory usage is possibly
	    quadratic in the number of items in the changeset.


	(2) A number of small inefficiencies. Like 'state eval' always
	    pulling the whole result into memory before processing it
	    with 'foreach'. Here potentially large lists.


	(3) We maintain an in-memory map from tagged items to their
	    changesets. While this is needed later in the sorting
	    passes during the creation this is wasted space. And also
	    wasted time, to maintain it during the creation and
	    breaking.

	Changes:

	(a) Re-architect to create, break, and persist changesets one
	    by one, completely releasing all associated in-memory data
	    before going to the next. Should be low-hanging fruit with
	    high impact, as we have all the necessary operations
	    already, just not in that order, and that alone should
	    already keep the pile from forming, making the spikes of
	    (2) more manageable.

	(b) Look into the smaller problems described in (2), and
	    especially (3). These should still be low-hanging fruit,
	    although of lesser effect than (a). For (3) disable the
	    map and its maintenace during construction, and put it
	    into a separate command, to be used when loading the
	    created changesets at the end.

	(c) With larger effect, but more difficult to achieve, go into
	    command 'InitializeBreakState' and the preceding
	    'internalsuccessors', and rearchitect it. Definitely not a
	    low-hanging fruit. Possibly also something we can skip if
	    doing (a) had a large enough effect.


*	Look at the dependencies on external packages and consider
	which of them can be moved into the importer, either as a
	simple utility command, or wholesale.

	struct::list
		assign, map, reverse, filter







|
|

|
<

>
|
|
|
|
|
|
|
|
|
<
>
|
|
|
<
>
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>







3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24

25
26
27
28

29
30
31
32
33
34























35
36
37
38
39
40
41
42
===================================

*	Not yet able to handle the specification of multiple projects
	for one CVS repository. I.e. I can, for example, import all of
	tcllib, or a single subproject of tcllib, like tklib, but not
	multiple sub-projects in one go.

*	Consider to rework the breaker- and sort-passes so that they
        do not need all changesets as objects in memory.

	Current memory consumption after all changesets are loaded:


	bwidget		 6971627    6.6
	cvs-memchan	 4634049    4.4
	cvs-sqlite	45674501   43.6
	cvs-trf		 8781289    8.4
	faqs		 2835116    2.7
	libtommath	 4405066    4.2
	mclistbox	 3350190    3.2 
	newclock	 5020460    4.8
	oocore		 4064574    3.9
	sampleextension	 4729932    4.5

	tclapps		 8482135    8.1
	tclbench	 4116887    3.9
	tcl_bignum	 2545192    2.4
	tclconfig	 4105042    3.9

	tcllib		31707688   30.2
	tcltutorial	 3512048    3.3
	tcl	       109926382  104.8
	thread		 8953139    8.5
	tklib		13935220   13.3
	tk		66149870   63.1























	widget		 2625609    2.5

*	Look at the dependencies on external packages and consider
	which of them can be moved into the importer, either as a
	simple utility command, or wholesale.

	struct::list
		assign, map, reverse, filter

Changes to tools/cvs2fossil/lib/c2f_file.tcl.

312
313
314
315
316
317
318
319
320






321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
	#       all, even those without revision, for both proper
	#       ordering and exact patch application.

	set earcs   {} ; # Arcs for expansion graph
	set zarcs   {} ; # Arcs for zip graph
	set revmap  {} ; # path -> rid map to later merge uuid information

	foreach {rid revnr parent child coff clen cid cparent} [state run {
	    SELECT B.rid, R.rev, R.parent, R.child, B.coff, B.clen, B.bid, B.pid






	    FROM            blob B
	    LEFT OUTER JOIN revision R
	    ON              B.rid = R.rid
	    WHERE  B.fid = $myid
	}] {
	    # Main data are blobs, most will have revisions, but not
	    # all. The expansion graph is blob based, whereas the
	    # recompression graph is revision based.

	    if {$revnr ne ""} {
		# Blob has revision, extend recompression graph.

		lappend revmap r$revnr $rid

		$zp node insert $rid
		$zp node set    $rid revnr $revnr
		$zp node set    $rid label <$revnr>

		if {$child ne ""} {
		    lappend zarcs $child $rid
		}
	    } else {
		# We fake a revnr for the blobs which have no
		# revision, for use in the expansion graph.
		set revnr ghost$cid
	    }

	    # Now the expansion graph.

	    $ex node insert $cid
	    $ex node set    $cid text  [list $coff $clen]
	    $ex node set    $cid revnr $revnr
	    $ex node set    $cid label <$revnr>

	    if {$cparent ne ""} {
		# The expansion arcs go from baseline to delta
		# descendant, based on the blob information.
		lappend earcs $cparent $cid







|
|
>
>
>
>
>
>




|







|

|
|
|

|
|










|







312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
	#       all, even those without revision, for both proper
	#       ordering and exact patch application.

	set earcs   {} ; # Arcs for expansion graph
	set zarcs   {} ; # Arcs for zip graph
	set revmap  {} ; # path -> rid map to later merge uuid information

	state foreachrow {
	    SELECT B.rid    AS xrid,
	           R.rev    AS revnr,
	           R.child  AS xchild,
	           B.coff   AS xcoff,
	           B.clen   AS xclen,
	           B.bid    AS cid,
	           B.pid    AS cparent
	    FROM            blob B
	    LEFT OUTER JOIN revision R
	    ON              B.rid = R.rid
	    WHERE  B.fid = $myid
	} {
	    # Main data are blobs, most will have revisions, but not
	    # all. The expansion graph is blob based, whereas the
	    # recompression graph is revision based.

	    if {$revnr ne ""} {
		# Blob has revision, extend recompression graph.

		lappend revmap r$revnr $xrid

		$zp node insert $xrid
		$zp node set    $xrid revnr $revnr
		$zp node set    $xrid label <$revnr>

		if {$xchild ne ""} {
		    lappend zarcs $xchild $xrid
		}
	    } else {
		# We fake a revnr for the blobs which have no
		# revision, for use in the expansion graph.
		set revnr ghost$cid
	    }

	    # Now the expansion graph.

	    $ex node insert $cid
	    $ex node set    $cid text  [list $xcoff $xclen]
	    $ex node set    $cid revnr $revnr
	    $ex node set    $cid label <$revnr>

	    if {$cparent ne ""} {
		# The expansion arcs go from baseline to delta
		# descendant, based on the blob information.
		lappend earcs $cparent $cid

Changes to tools/cvs2fossil/lib/c2f_frev.tcl.

511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
	{0 0} change
	{0 1} delete
	{1 0} add
	{1 1} nothing
    }

    typemethod getopcodes {} {
	foreach {id name} [state run {
	    SELECT oid, name FROM optype;
	}] { set myopcode($name) $id }
	return
    }

    typevariable myopcode -array {}

    # # ## ### ##### ######## #############
    ## Internal methods







|

|







511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
	{0 0} change
	{0 1} delete
	{1 0} add
	{1 1} nothing
    }

    typemethod getopcodes {} {
	state foreachrow {
	    SELECT oid, name FROM optype;
	} { set myopcode($name) $oid }
	return
    }

    typevariable myopcode -array {}

    # # ## ### ##### ######## #############
    ## Internal methods

Changes to tools/cvs2fossil/lib/c2f_pbreakacycle.tcl.

109
110
111
112
113
114
115

116

117
118
119
120
121
122
123
	::variable mycset
	::variable myrevisionchangesets

	log write 2 breakacycle {Loading revision commit order}

	set n 0
	state transaction {

	    foreach {cid pos} [state run { SELECT cid, pos FROM csorder }] {

		log progress 2 breakacycle $n {}
		set cset [project::rev of $cid]
		$cset setpos $pos
		set mycset($pos) $cset
		lappend myrevisionchangesets $cset
		incr n
	    }







>
|
>







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
	::variable mycset
	::variable myrevisionchangesets

	log write 2 breakacycle {Loading revision commit order}

	set n 0
	state transaction {
	    state foreachrow {
		SELECT cid, pos FROM csorder
	    } {
		log progress 2 breakacycle $n {}
		set cset [project::rev of $cid]
		$cset setpos $pos
		set mycset($pos) $cset
		lappend myrevisionchangesets $cset
		incr n
	    }

Changes to tools/cvs2fossil/lib/c2f_pcollsym.tcl.

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
...
222
223
224
225
226
227
228
229
230





231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
	return
    }

    # # ## ### ##### ######## #############
    ## Internal methods

    ## TODO: Move UnconvertedSymbols, BadSymbolTypes, BlockedIncludes,
    ##       InvalidTags to the integrity module?

    proc UnconvertedSymbols {} {
	# Paranoia - Have we left symbols without conversion
	# information (i.e. with type 'undefined') ?

	set undef [project::sym undef]

	foreach {pname sname} [state run {
	    SELECT P.name, S.name
	    FROM   symbol S, project P
	    WHERE  S.type = $undef  -- Restrict to undefined symbols
	    AND    P.pid = S.pid    -- Get project for symbol
	}] {
	    trouble fatal "$pname : The symbol '$sname' was left undefined"
	}
	return
    }

    proc BadSymbolTypes {} {
	# Paranoia - Have we left symbols with bogus conversion
	# information (type out of the valid range (excluded, branch,
	# tag)) ?

	foreach {pname sname} [state run {
	    SELECT P.name, S.name
	    FROM   symbol S, project P
	    WHERE  S.type NOT IN (0,1,2) -- Restrict to symbols with bogus type codes
	    AND    P.pid = S.pid         -- Get project of symbol
	}] {
	    trouble fatal "$pname : The symbol '$sname' has no proper conversion type"
	}
	return
    }

    proc BlockedExcludes {} {
	# Paranoia - Have we scheduled symbols for exclusion without
	# also excluding their dependent symbols ?

	set excl [project::sym excluded]

	foreach {pname sname bname} [state run {
	    SELECT P.name, S.name, SB.name
	    FROM   symbol S, blocker B, symbol SB, project P
	    WHERE  S.type = $excl   -- Restrict to excluded symbols
	    AND    S.sid = B.sid    -- Get symbols blocking them
	    AND    B.bid = SB.sid   -- and
	    AND    SB.type != $excl -- which are not excluded themselves
	    AND    P.pid = S.pid    -- Get project of symbol
	}] {
	    trouble fatal "$pname : The symbol '$sname' cannot be excluded as the unexcluded symbol '$bname' depends on it."
	}
	return
    }

    proc InvalidTags {} {
	# Paranoia - Have we scheduled symbols for conversion as tags
................................................................................
	# In other words, this checks finds out if the user has asked
	# nonsensical conversions of symbols, which should have been
	# left to the heuristics, most specifically
	# 'project::sym.HasCommits()'.

	set tag [project::sym tag]

	foreach {pname sname} [state run {
	    SELECT P.name, S.name
	    FROM   project P, symbol S
	    WHERE  S.type = $tag        -- Restrict to tag symbols
	    AND    S.commit_count > 0   -- which have revisions committed to them
	    AND    P.pid = S.pid        -- Get project of symbol
	}] {
	    trouble fatal "$pname : The symbol '$sname' cannot be forced to be converted as tag because it has commits."
	}
	return
    }

    proc DropExcludedSymbolsFromReferences {} {
	# The excluded symbols cann be used as blockers nor as
................................................................................
	#          prefered parent of each symbol last among all
	#          candidates, allowing us get the prefered one by
	#          each candidate overwriting all previous
	#          selections. Note that we ignore excluded symbol, we
	#          do not care about their prefered parents and do not
	#          attempt to compute them.

	foreach {s p sname pname prname votes} [state run {
	    SELECT   S.sid, P.pid, S.name, SB.name, PR.name, P.n





	    FROM     symbol S, parent P, symbol SB, project PR
	    WHERE    S.type != $excl      -- Restrict to wanted symbols
	    AND      S.sid = P.sid        -- Get possible parents of symbol
	    AND      P.pid = SB.sid       -- and
	    AND      S.pid = PR.pid       -- the project of the symbol
	    ORDER BY P.n ASC, P.pid DESC  -- Sorting, see below
	    --
	    -- Higher votes and smaller ids (= earlier branches) last
	    -- We simply keep the last possible parent for each
	    -- symbol.  This parent will have the max number of votes
	    -- for its symbol and will be the earliest created branch
	    -- possible among all with many votes.
	}] {
	    log write 9 pcollsym "Voting $votes for Parent($sname) = $pname"

	    set prefered($s) [list $p $sname $pname $prname]
	}

	# Phase II: Write the found preferences back into the table
	#           this pass defined for it.

	foreach {s x} [array get prefered] {
	    struct::list assign $x p sname pname prname
................................................................................
	}

	# Phase III: Check the result that all symbols except for
	#            trunks have a prefered parent. We also ignore
	#            excluded symbols, as we intentionally did not
	#            compute a prefered parent for them, see phase I.

	foreach {pname sname} [state run {
	    SELECT PR.name, S.name
	    FROM   symbol S LEFT OUTER JOIN preferedparent P
	    ON     S.sid = P.sid,       -- From symbol to prefered parent
	           project PR
	    WHERE  P.pid IS NULL        -- restrict to symbols without a preference
	    AND    S.type != $excl      -- which are not excluded
	    AND    S.name != ':trunk:'  -- and are not a trunk
	    AND    S.pid = PR.pid       -- get project of symbol
	}] {
	    trouble fatal "$pname : '$sname' has no prefered parent."
	}

	# The reverse, having prefered parents for unknown symbols
	# cannot occur.
	return
    }







|







|
|



|










|
|



|











|
|






|







 







|
|




|







 







|
|
>
>
>
>
>












|


|







 







|
|







|







110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
	return
    }

    # # ## ### ##### ######## #############
    ## Internal methods

    ## TODO: Move UnconvertedSymbols, BadSymbolTypes, BlockedIncludes,
    ## TODO: InvalidTags to the integrity module?

    proc UnconvertedSymbols {} {
	# Paranoia - Have we left symbols without conversion
	# information (i.e. with type 'undefined') ?

	set undef [project::sym undef]

	state foreachrow {
	    SELECT P.name AS pname, S.name AS sname
	    FROM   symbol S, project P
	    WHERE  S.type = $undef  -- Restrict to undefined symbols
	    AND    P.pid = S.pid    -- Get project for symbol
	} {
	    trouble fatal "$pname : The symbol '$sname' was left undefined"
	}
	return
    }

    proc BadSymbolTypes {} {
	# Paranoia - Have we left symbols with bogus conversion
	# information (type out of the valid range (excluded, branch,
	# tag)) ?

	state foreachrow {
	    SELECT P.name AS pname, S.name AS sname
	    FROM   symbol S, project P
	    WHERE  S.type NOT IN (0,1,2) -- Restrict to symbols with bogus type codes
	    AND    P.pid = S.pid         -- Get project of symbol
	} {
	    trouble fatal "$pname : The symbol '$sname' has no proper conversion type"
	}
	return
    }

    proc BlockedExcludes {} {
	# Paranoia - Have we scheduled symbols for exclusion without
	# also excluding their dependent symbols ?

	set excl [project::sym excluded]

	state foreachrow {
	    SELECT P.name AS pname, S.name AS sname, SB.name AS bname
	    FROM   symbol S, blocker B, symbol SB, project P
	    WHERE  S.type = $excl   -- Restrict to excluded symbols
	    AND    S.sid = B.sid    -- Get symbols blocking them
	    AND    B.bid = SB.sid   -- and
	    AND    SB.type != $excl -- which are not excluded themselves
	    AND    P.pid = S.pid    -- Get project of symbol
	} {
	    trouble fatal "$pname : The symbol '$sname' cannot be excluded as the unexcluded symbol '$bname' depends on it."
	}
	return
    }

    proc InvalidTags {} {
	# Paranoia - Have we scheduled symbols for conversion as tags
................................................................................
	# In other words, this checks finds out if the user has asked
	# nonsensical conversions of symbols, which should have been
	# left to the heuristics, most specifically
	# 'project::sym.HasCommits()'.

	set tag [project::sym tag]

	state foreachrow {
	    SELECT P.name AS pname, S.name AS sname
	    FROM   project P, symbol S
	    WHERE  S.type = $tag        -- Restrict to tag symbols
	    AND    S.commit_count > 0   -- which have revisions committed to them
	    AND    P.pid = S.pid        -- Get project of symbol
	} {
	    trouble fatal "$pname : The symbol '$sname' cannot be forced to be converted as tag because it has commits."
	}
	return
    }

    proc DropExcludedSymbolsFromReferences {} {
	# The excluded symbols cann be used as blockers nor as
................................................................................
	#          prefered parent of each symbol last among all
	#          candidates, allowing us get the prefered one by
	#          each candidate overwriting all previous
	#          selections. Note that we ignore excluded symbol, we
	#          do not care about their prefered parents and do not
	#          attempt to compute them.

	state foreachrow {
	    SELECT   S.sid   AS xs,
	             P.pid   AS xp,
	             S.name  AS sname,
	             SB.name AS pname,
	             PR.name AS prname,
	             P.n     AS votes
	    FROM     symbol S, parent P, symbol SB, project PR
	    WHERE    S.type != $excl      -- Restrict to wanted symbols
	    AND      S.sid = P.sid        -- Get possible parents of symbol
	    AND      P.pid = SB.sid       -- and
	    AND      S.pid = PR.pid       -- the project of the symbol
	    ORDER BY P.n ASC, P.pid DESC  -- Sorting, see below
	    --
	    -- Higher votes and smaller ids (= earlier branches) last
	    -- We simply keep the last possible parent for each
	    -- symbol.  This parent will have the max number of votes
	    -- for its symbol and will be the earliest created branch
	    -- possible among all with many votes.
	} {
	    log write 9 pcollsym "Voting $votes for Parent($sname) = $pname"

	    set prefered($xs) [list $xp $sname $pname $prname]
	}

	# Phase II: Write the found preferences back into the table
	#           this pass defined for it.

	foreach {s x} [array get prefered] {
	    struct::list assign $x p sname pname prname
................................................................................
	}

	# Phase III: Check the result that all symbols except for
	#            trunks have a prefered parent. We also ignore
	#            excluded symbols, as we intentionally did not
	#            compute a prefered parent for them, see phase I.

	state foreachrow {
	    SELECT PR.name AS pname, S.name AS sname
	    FROM   symbol S LEFT OUTER JOIN preferedparent P
	    ON     S.sid = P.sid,       -- From symbol to prefered parent
	           project PR
	    WHERE  P.pid IS NULL        -- restrict to symbols without a preference
	    AND    S.type != $excl      -- which are not excluded
	    AND    S.name != ':trunk:'  -- and are not a trunk
	    AND    S.pid = PR.pid       -- get project of symbol
	} {
	    trouble fatal "$pname : '$sname' has no prefered parent."
	}

	# The reverse, having prefered parents for unknown symbols
	# cannot occur.
	return
    }

Changes to tools/cvs2fossil/lib/c2f_pfiltersym.tcl.

145
146
147
148
149
150
151
152
153


154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
...
529
530
531
532
533
534
535
536


537


538
539
540
541
542
543


544


545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
	# in-memory revision objects, which we do not have here. We do
	# the same now without object, by directly manipulating the
	# links in the database.

	array set ntdb {}
	array set link {}

	foreach {id parent transfer} [state run {
	    SELECT R.rid, R.parent, R.dbchild


	    FROM  revision R, symbol S
	    WHERE R.lod = S.sid            -- Get symbol of line-of-development of all revisions
	    AND   S.sid IN excludedsymbols -- Restrict to the excluded symbols
	    AND   R.isdefault              -- Restrict to NTDB revisions
	}] {
	    set ntdb($id) $parent
	    if {$transfer eq ""} continue
	    set link($id) $transfer
	}

	foreach joint [array names link] {
	    # The joints are the highest NTDB revisions which are
	    # shared with their respective trunk. We disconnect from
	    # their NTDB children, and make them parents of their
	    # 'dbchild'. The associated 'dbparent' is squashed
................................................................................
	# Tag/Branch names ...
	array set sn [state run { SELECT T.tid, S.name FROM tag T,    symbol S WHERE T.sid = S.sid }]
	array set sn [state run { SELECT B.bid, S.name FROM branch B, symbol S WHERE B.sid = S.sid }]
	# Symbol names ...
	array set sx [state run { SELECT L.sid, L.name FROM symbol L }]
	# Files and projects.
	array set fpn {}
	foreach {id fn pn} [state run {
		SELECT F.fid, F.name, P.name
		FROM   file F, project P
		WHERE  F.pid = P.pid
	}] { set fpn($id) [list $fn $pn] }

	set tagstoadjust [state run {
	    SELECT T.tid, T.fid, T.lod, P.pid, S.name, R.rev, R.rid
	    FROM tag T, preferedparent P, symbol S, revision R
	    WHERE T.sid = P.sid        -- For all tags, get left-hand of prefered parent via symbol
	    AND   T.lod != P.pid       -- Restrict to tags whose LOD is not their prefered parent
	    AND   P.pid = S.sid        -- Get symbol of prefered parent
................................................................................
	if {![log visible? 9]} return

	array set sym {}
	set n 0
	set t 0
	set c 0

	foreach {s stype cc p ptype} [state run {


	    SELECT S.name, A.name, S.commit_count, P.name, B.name


	    FROM   tag T, symbol S, symbol P, symtype A, symtype B
	    WHERE  S.sid = T.sid
	    AND    P.sid = T.lod
	    AND    A.tid = S.type
	    AND    B.tid = P.type
	    UNION


	    SELECT S.name, A.name, S.commit_count, P.name, B.name


	    FROM   branch B, symbol S, symbol P, symtype A, symtype B
	    WHERE  S.sid = B.sid
	    AND    P.sid = B.lod
	    AND    A.tid = S.type
	    AND    B.tid = P.type
	}] {
	    lappend sym($s) $p $stype $ptype $cc
	    maxlen n $s
	    maxlen t $stype
	    maxlen t $ptype
	    maxlen c $cc
	}

	foreach s [lsort -dict [array names sym]] {
	    struct::list assign $sym($s) p stype ptype cc







|
|
>
>




|
|

|







 







|
|


|







 







|
>
>
|
>
>






>
>
|
>
>





|
|
|







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
...
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
...
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
	# in-memory revision objects, which we do not have here. We do
	# the same now without object, by directly manipulating the
	# links in the database.

	array set ntdb {}
	array set link {}

	state foreachrow {
	    SELECT R.rid     AS xid,
	           R.parent  AS xparent,
	           R.dbchild AS transfer
	    FROM  revision R, symbol S
	    WHERE R.lod = S.sid            -- Get symbol of line-of-development of all revisions
	    AND   S.sid IN excludedsymbols -- Restrict to the excluded symbols
	    AND   R.isdefault              -- Restrict to NTDB revisions
	} {
	    set ntdb($xid) $xparent
	    if {$transfer eq ""} continue
	    set link($xid) $transfer
	}

	foreach joint [array names link] {
	    # The joints are the highest NTDB revisions which are
	    # shared with their respective trunk. We disconnect from
	    # their NTDB children, and make them parents of their
	    # 'dbchild'. The associated 'dbparent' is squashed
................................................................................
	# Tag/Branch names ...
	array set sn [state run { SELECT T.tid, S.name FROM tag T,    symbol S WHERE T.sid = S.sid }]
	array set sn [state run { SELECT B.bid, S.name FROM branch B, symbol S WHERE B.sid = S.sid }]
	# Symbol names ...
	array set sx [state run { SELECT L.sid, L.name FROM symbol L }]
	# Files and projects.
	array set fpn {}
	state foreachrow {
		SELECT F.fid AS id, F.name AS fn, P.name AS pn
		FROM   file F, project P
		WHERE  F.pid = P.pid
	} { set fpn($id) [list $fn $pn] }

	set tagstoadjust [state run {
	    SELECT T.tid, T.fid, T.lod, P.pid, S.name, R.rev, R.rid
	    FROM tag T, preferedparent P, symbol S, revision R
	    WHERE T.sid = P.sid        -- For all tags, get left-hand of prefered parent via symbol
	    AND   T.lod != P.pid       -- Restrict to tags whose LOD is not their prefered parent
	    AND   P.pid = S.sid        -- Get symbol of prefered parent
................................................................................
	if {![log visible? 9]} return

	array set sym {}
	set n 0
	set t 0
	set c 0

	state foreachrow {
	    SELECT S.name         AS xs,
	           A.name         AS stype,
	           S.commit_count AS cc,
	           P.name         AS xp,
	           B.name         AS ptype
	    FROM   tag T, symbol S, symbol P, symtype A, symtype B
	    WHERE  S.sid = T.sid
	    AND    P.sid = T.lod
	    AND    A.tid = S.type
	    AND    B.tid = P.type
	    UNION
	    SELECT S.name         AS xs,
	           A.name         AS stype,
	           S.commit_count AS cc,
	           P.name         AS xp,
	           B.name         AS ptype
	    FROM   branch B, symbol S, symbol P, symtype A, symtype B
	    WHERE  S.sid = B.sid
	    AND    P.sid = B.lod
	    AND    A.tid = S.type
	    AND    B.tid = P.type
	} {
	    lappend sym($xs) $xp $stype $ptype $cc
	    maxlen n $xs
	    maxlen t $stype
	    maxlen t $ptype
	    maxlen c $cc
	}

	foreach s [lsort -dict [array names sym]] {
	    struct::list assign $sym($s) p stype ptype cc

Changes to tools/cvs2fossil/lib/c2f_prev.tcl.

323
324
325
326
327
328
329
330
331
332




333
334
335
336
337
338
339
340
341
342
343
344
...
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
...
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
....
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
....
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
	}
	return
    }

    proc Getrevisioninfo {revisions} {
	set theset ('[join $revisions {','}]')
	set revisions {}
	#foreachrow
	foreach {frid path fname revnr rop} [state run [subst -nocommands -nobackslashes {
	    SELECT U.uuid, F.visible, F.name, R.rev, R.op




	    FROM   revision R, revuuid U, file F
	    WHERE  R.rid IN $theset  -- All specified revisions
	    AND    U.rid = R.rid     -- get fossil uuid of revision
	    AND    F.fid = R.fid     -- get file of revision
	}]] {
	    lappend revisions $frid $path $fname/$revnr $rop
	}
	return $revisions
    }

    proc Getworkspace {rstate lodname project isdefault} {

................................................................................
    typemethod inorder {projectid} {
	# Return all revision changesets for the specified project, in
	# the order given to them by the sort passes. Both the
	# filtering by project and sorting make use of 'project::rev
	# rev' impossible.

	set res {}
	#foreachrow
	foreach {cid cdate} [state run {
	    SELECT C.cid, T.date
	    FROM   changeset C, cstimestamp T
	    WHERE  C.type = 0          -- limit to revision changesets
	    AND    C.pid  = $projectid -- limit to changesets in project
	    AND    T.cid  = C.cid      -- get ordering information
	    ORDER BY T.date            -- sort into commit order
	}] {
	    lappend res $myidmap($cid) $cdate
	}
	return $res
    }

    typemethod getcstypes {} {
	state foreachrow {
	    SELECT tid, name FROM cstype;
................................................................................
	# Pull the timestamps for all revisions in the changesets and
	# compute their deltas for use by the break finder.

	array set delta {}
	array set stamp {}

	set theset ('[join $revisions {','}]')
	#foreachrow
	foreach {rid time} [state run [subst -nocommands -nobackslashes {
	    SELECT R.rid, R.date
	    FROM revision R
	    WHERE R.rid IN $theset
	}]] {
	    set stamp($rid) $time
	}

	log write 14 csets {IBS: stamp [array size stamp]}

	set n 0
	foreach rid [lrange $revisions 0 end-1] rnext [lrange $revisions 1 end] {
	    set delta($n) [expr {$stamp($rnext) - $stamp($rid)}]
................................................................................
	# (4) If R is the last of the NTDB revisions which belong to
	#     the trunk, then the primary child of the trunk root (the
	#     '1.2' revision) is a successor, if it exists.

	# Note that the branches spawned from the revisions, and the
	# tags associated with them are successors as well.

	#foreachrow
	foreach {rid child} [state run [subst -nocommands -nobackslashes {
    -- (1) Primary child
	    SELECT R.rid, R.child
	    FROM   revision R
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.child IS NOT NULL    -- Has primary child
    UNION
    -- (2) Secondary (branch) children
	    SELECT R.rid, B.brid
	    FROM   revision R, revisionbranchchildren B
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.rid = B.rid          -- Select subset of branch children
    UNION
    -- (4) Child of trunk root successor of last NTDB on trunk.
	    SELECT R.rid, RA.child
	    FROM revision R, revision RA
	    WHERE R.rid   IN $theset      -- Restrict to revisions of interest
	    AND   R.isdefault             -- Restrict to NTDB
	    AND   R.dbchild IS NOT NULL   -- and last NTDB belonging to trunk
	    AND   RA.rid = R.dbchild      -- Go directly to trunk root
	    AND   RA.child IS NOT NULL    -- Has primary child.
	}]] {
	    # Consider moving this to the integrity module.
	    integrity assert {$rid != $child} {Revision $rid depends on itself.}
	    lappend dependencies([list rev $rid]) [list rev $child]
	}
	#foreachrow
	foreach {rid child} [state run [subst -nocommands -nobackslashes {
	    SELECT R.rid, T.tid
	    FROM   revision R, tag T
	    WHERE  R.rid IN $theset       -- Restrict to revisions of interest
	    AND    T.rev = R.rid          -- Select tags attached to them
	}]] {
	    lappend dependencies([list rev $rid]) [list sym::tag $child]
	}
	#foreachrow
	foreach {rid child} [state run [subst -nocommands -nobackslashes {
	    SELECT R.rid, B.bid
	    FROM   revision R, branch B
	    WHERE  R.rid IN $theset       -- Restrict to revisions of interest
	    AND    B.root = R.rid         -- Select branches attached to them
	}]] {
	    lappend dependencies([list rev $rid]) [list sym::branch $child]
	}
	return
    }

    # result = list (changeset-id)
    typemethod cs_successors {revisions} {
        # This is a variant of 'successors' which maps the low-level
................................................................................
    typemethod successors {dv branches} {
	upvar 1 $dv dependencies
	# The first revision committed on a branch, and all branches
	# and tags which have it as their prefered parent are the
	# successors of a branch.

	set theset ('[join $branches {','}]')
	#foreachrow
	foreach {bid child} [state run [subst -nocommands -nobackslashes {
	    SELECT B.bid, R.rid
	    FROM   branch B, revision R
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.first = R.rid      -- Get first revision on the branch
	}]] {
	    lappend dependencies([list sym::branch $bid]) [list rev $child]
	}
	#foreachrow
	foreach {bid child} [state run [subst -nocommands -nobackslashes {
	    SELECT B.bid, BX.bid
	    FROM   branch B, preferedparent P, branch BX
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.sid = P.pid        -- Get subordinate branches via the
	    AND    BX.sid = P.sid       -- prefered parents of their symbols
	}]] {
	    lappend dependencies([list sym::branch $bid]) [list sym::branch $child]
	}
	#foreachrow
	foreach {bid child} [state run [subst -nocommands -nobackslashes {
	    SELECT B.bid, T.tid
	    FROM   branch B, preferedparent P, tag T
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.sid = P.pid        -- Get subordinate tags via the
	    AND    T.sid = P.sid        -- prefered parents of their symbols
	}]] {
	    lappend dependencies([list sym::branch $bid]) [list sym::tag $child]
	}
	return
    }

    # result = list (changeset-id)
    typemethod cs_successors {branches} {
        # This is a variant of 'successors' which maps the low-level







<
|
|
>
>
>
>




|







 







|
<
|





|
|







 







<
|
|


|
|







 







<
|

|





|





|






|

|
|

<
|
|



|
|

<
|
|



|
|







 







<
|
|



|
|

<
|
|




|
|

<
|
|




|
|







323
324
325
326
327
328
329

330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
...
585
586
587
588
589
590
591
592

593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
...
899
900
901
902
903
904
905

906
907
908
909
910
911
912
913
914
915
916
917
918
....
1325
1326
1327
1328
1329
1330
1331

1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357

1358
1359
1360
1361
1362
1363
1364
1365

1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
....
1577
1578
1579
1580
1581
1582
1583

1584
1585
1586
1587
1588
1589
1590
1591

1592
1593
1594
1595
1596
1597
1598
1599
1600

1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
	}
	return
    }

    proc Getrevisioninfo {revisions} {
	set theset ('[join $revisions {','}]')
	set revisions {}

	state foreachrow [subst -nocommands -nobackslashes {
	    SELECT U.uuid    AS frid,
	           F.visible AS path,
	           F.name    AS fname,
	           R.rev     AS revnr,
	           R.op      AS rop
	    FROM   revision R, revuuid U, file F
	    WHERE  R.rid IN $theset  -- All specified revisions
	    AND    U.rid = R.rid     -- get fossil uuid of revision
	    AND    F.fid = R.fid     -- get file of revision
	}] {
	    lappend revisions $frid $path $fname/$revnr $rop
	}
	return $revisions
    }

    proc Getworkspace {rstate lodname project isdefault} {

................................................................................
    typemethod inorder {projectid} {
	# Return all revision changesets for the specified project, in
	# the order given to them by the sort passes. Both the
	# filtering by project and sorting make use of 'project::rev
	# rev' impossible.

	set res {}
	state foreachrow {

	    SELECT C.cid AS xcid, T.date AS cdate
	    FROM   changeset C, cstimestamp T
	    WHERE  C.type = 0          -- limit to revision changesets
	    AND    C.pid  = $projectid -- limit to changesets in project
	    AND    T.cid  = C.cid      -- get ordering information
	    ORDER BY T.date            -- sort into commit order
	} {
	    lappend res $myidmap($xcid) $cdate
	}
	return $res
    }

    typemethod getcstypes {} {
	state foreachrow {
	    SELECT tid, name FROM cstype;
................................................................................
	# Pull the timestamps for all revisions in the changesets and
	# compute their deltas for use by the break finder.

	array set delta {}
	array set stamp {}

	set theset ('[join $revisions {','}]')

	state foreachrow [subst -nocommands -nobackslashes {
	    SELECT R.rid AS xrid, R.date AS time
	    FROM revision R
	    WHERE R.rid IN $theset
	}] {
	    set stamp($xrid) $time
	}

	log write 14 csets {IBS: stamp [array size stamp]}

	set n 0
	foreach rid [lrange $revisions 0 end-1] rnext [lrange $revisions 1 end] {
	    set delta($n) [expr {$stamp($rnext) - $stamp($rid)}]
................................................................................
	# (4) If R is the last of the NTDB revisions which belong to
	#     the trunk, then the primary child of the trunk root (the
	#     '1.2' revision) is a successor, if it exists.

	# Note that the branches spawned from the revisions, and the
	# tags associated with them are successors as well.


	state foreachrow [subst -nocommands -nobackslashes {
    -- (1) Primary child
	    SELECT R.rid AS xrid, R.child AS xchild
	    FROM   revision R
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.child IS NOT NULL    -- Has primary child
    UNION
    -- (2) Secondary (branch) children
	    SELECT R.rid AS xrid, B.brid AS xchild
	    FROM   revision R, revisionbranchchildren B
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.rid = B.rid          -- Select subset of branch children
    UNION
    -- (4) Child of trunk root successor of last NTDB on trunk.
	    SELECT R.rid AS xrid, RA.child AS xchild
	    FROM revision R, revision RA
	    WHERE R.rid   IN $theset      -- Restrict to revisions of interest
	    AND   R.isdefault             -- Restrict to NTDB
	    AND   R.dbchild IS NOT NULL   -- and last NTDB belonging to trunk
	    AND   RA.rid = R.dbchild      -- Go directly to trunk root
	    AND   RA.child IS NOT NULL    -- Has primary child.
	}] {
	    # Consider moving this to the integrity module.
	    integrity assert {$xrid != $xchild} {Revision $xrid depends on itself.}
	    lappend dependencies([list rev $xrid]) [list rev $xchild]
	}

	state foreachrow [subst -nocommands -nobackslashes {
	    SELECT R.rid AS xrid, T.tid AS xchild
	    FROM   revision R, tag T
	    WHERE  R.rid IN $theset       -- Restrict to revisions of interest
	    AND    T.rev = R.rid          -- Select tags attached to them
	}] {
	    lappend dependencies([list rev $xrid]) [list sym::tag $xchild]
	}

	state foreachrow [subst -nocommands -nobackslashes {
	    SELECT R.rid AS xrid, B.bid AS xchild
	    FROM   revision R, branch B
	    WHERE  R.rid IN $theset       -- Restrict to revisions of interest
	    AND    B.root = R.rid         -- Select branches attached to them
	}] {
	    lappend dependencies([list rev $xrid]) [list sym::branch $xchild]
	}
	return
    }

    # result = list (changeset-id)
    typemethod cs_successors {revisions} {
        # This is a variant of 'successors' which maps the low-level
................................................................................
    typemethod successors {dv branches} {
	upvar 1 $dv dependencies
	# The first revision committed on a branch, and all branches
	# and tags which have it as their prefered parent are the
	# successors of a branch.

	set theset ('[join $branches {','}]')

	state foreachrow [subst -nocommands -nobackslashes {
	    SELECT B.bid AS xbid, R.rid AS xchild
	    FROM   branch B, revision R
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.first = R.rid      -- Get first revision on the branch
	}] {
	    lappend dependencies([list sym::branch $xbid]) [list rev $xchild]
	}

	state foreachrow [subst -nocommands -nobackslashes {
	    SELECT B.bid AS xbid, BX.bid AS xchild
	    FROM   branch B, preferedparent P, branch BX
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.sid = P.pid        -- Get subordinate branches via the
	    AND    BX.sid = P.sid       -- prefered parents of their symbols
	}] {
	    lappend dependencies([list sym::branch $xbid]) [list sym::branch $xchild]
	}

	state foreachrow [subst -nocommands -nobackslashes {
	    SELECT B.bid AS xbid, T.tid AS xchild
	    FROM   branch B, preferedparent P, tag T
	    WHERE  B.bid IN $theset     -- Restrict to branches of interest
	    AND    B.sid = P.pid        -- Get subordinate tags via the
	    AND    T.sid = P.sid        -- prefered parents of their symbols
	}] {
	    lappend dependencies([list sym::branch $xbid]) [list sym::tag $xchild]
	}
	return
    }

    # result = list (changeset-id)
    typemethod cs_successors {branches} {
        # This is a variant of 'successors' which maps the low-level

Changes to tools/cvs2fossil/lib/c2f_psym.tcl.

247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
297
298
299
300
301
302
303
304


305
306
307
308
309
310
311
312
313
314
315
316
317
318
...
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
				       # branches.

    typevariable myforcepattern {} ; # List of patterns and types
				     # specifying which symbols to
				     # force to specific types.

    typemethod getsymtypes {} {
	foreach {tid name} [state run {
	    SELECT tid, name FROM symtype;
	}] { set mysymtype($tid) $name }
	return
    }

    # Keep the codes below in sync with 'pass::collrev/setup('symtype').
    typevariable myexcluded        0 ; # Code for symbols which are excluded.
    typevariable mytag             1 ; # Code for symbols which are tags.
    typevariable mybranch          2 ; # Code for symbols which are branches.
................................................................................

    typemethod printtypestatistics {} {
	log write 2 symbol "Symbol type statistics:"

	set fmt %[string length $mynum]s
	set all 0

	foreach {stype splural n} [state run {


	    SELECT T.name, T.plural, COUNT (s.sid)
	    FROM symbol S, symtype T
	    WHERE S.type = T.tid
	    GROUP BY T.name
	    ORDER BY T.name
	    ;
	}] {
	    log write 2 symbol "* [format $fmt $n] [sp $n $stype $splural]"
	    incr all $n
	}

	log write 2 symbol "= [format $fmt $all] total"
	return
    }
................................................................................

	set mytype $chosen
	incr myrulecount($label)

	# This is stored directly into the database.
	state run {
	    UPDATE symbol
	    SET type = $chosen
	    WHERE sid = $myid
	    ;
	}
	return
    }

    # # ## ### ##### ######## #############
    ## Configuration








|

|







 







|
>
>
|




|
<







 







|
|
<







247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312

313
314
315
316
317
318
319
...
390
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
				       # branches.

    typevariable myforcepattern {} ; # List of patterns and types
				     # specifying which symbols to
				     # force to specific types.

    typemethod getsymtypes {} {
	state foreachrow {
	    SELECT tid, name FROM symtype;
	} { set mysymtype($tid) $name }
	return
    }

    # Keep the codes below in sync with 'pass::collrev/setup('symtype').
    typevariable myexcluded        0 ; # Code for symbols which are excluded.
    typevariable mytag             1 ; # Code for symbols which are tags.
    typevariable mybranch          2 ; # Code for symbols which are branches.
................................................................................

    typemethod printtypestatistics {} {
	log write 2 symbol "Symbol type statistics:"

	set fmt %[string length $mynum]s
	set all 0

	state foreachrow {
	    SELECT T.name        AS stype,
	           T.plural      AS splural,
	           COUNT (s.sid) AS n
	    FROM symbol S, symtype T
	    WHERE S.type = T.tid
	    GROUP BY T.name
	    ORDER BY T.name
	} {

	    log write 2 symbol "* [format $fmt $n] [sp $n $stype $splural]"
	    incr all $n
	}

	log write 2 symbol "= [format $fmt $all] total"
	return
    }
................................................................................

	set mytype $chosen
	incr myrulecount($label)

	# This is stored directly into the database.
	state run {
	    UPDATE symbol
	    SET    type = $chosen
	    WHERE  sid  = $myid

	}
	return
    }

    # # ## ### ##### ######## #############
    ## Configuration

Changes to tools/cvs2fossil/lib/c2f_repository.tcl.

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
...
242
243
244
245
246
247
248
249
250
251
252
253

254
255
256
257
258
259
260
...
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
	    }
	}
	return
    }

    typemethod load {} {
	state transaction {
	    foreach   {pid  name} [state run {
		SELECT pid, name FROM project ;
	    }] {
		set project [project %AUTO% $name $type]

		lappend myprojpaths $name
		lappend myprojects  $project
		set myprojmap($pid) $project
		$project setid $pid
	    }
	    foreach   {fid  pid  name  visible  exec} [state run {
		SELECT fid, pid, name, visible, exec FROM file ;
	    }] {
		$myprojmap($pid) addfile $name $visible $exec $fid
	    }
	}
	return
    }

    # pass II results
................................................................................
    }

    typemethod loadsymbols {} {
	state transaction {
	    # We load the symbol ids at large to have the mapping
	    # right from the beginning.

	    foreach {sid pid name tc bc cc} [state run {
		SELECT sid, pid, name, tag_count, branch_count, commit_count
		FROM symbol
		;
	    }] {

		$mysymbol map $sid [list $pid $name]
		set project $myprojmap($pid)

		set force  [$project hassymbol $name]
		set symbol [$project getsymbol $name]

		# Forcing happens only for the trunks.
................................................................................

		# future: $symbol load (blockers, and parents)
	    }

	    # Beyond the symbols we also load the author, commit log,
	    # and meta information.

	    foreach {aid aname} [state run {
		SELECT aid, name FROM author
	    }] {
		$myauthor map $aid $aname
	    }
	    foreach {cid text} [state run {
		SELECT cid, text FROM cmessage
	    }] {
		$mycmsg map $cid $text
	    }
	    foreach {mid pid bid aid cid} [state run {
		SELECT mid, pid, bid, aid, cid FROM meta
	    }] {
		$mymeta map $mid [list $pid $bid $aid $cid]
	    }
	}
	return
    }

    typemethod determinesymboltypes {} {







|

|







|

|







 







|
|

<
<
>







 







|
|
|


|

|


|

|







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
...
242
243
244
245
246
247
248
249
250
251


252
253
254
255
256
257
258
259
...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
	    }
	}
	return
    }

    typemethod load {} {
	state transaction {
	    state foreachrow {
		SELECT pid, name FROM project ;
	    } {
		set project [project %AUTO% $name $type]

		lappend myprojpaths $name
		lappend myprojects  $project
		set myprojmap($pid) $project
		$project setid $pid
	    }
	    state foreachrow {
		SELECT fid, pid, name, visible, exec FROM file ;
	    } {
		$myprojmap($pid) addfile $name $visible $exec $fid
	    }
	}
	return
    }

    # pass II results
................................................................................
    }

    typemethod loadsymbols {} {
	state transaction {
	    # We load the symbol ids at large to have the mapping
	    # right from the beginning.

	    state foreachrow {
		SELECT sid, pid, name, tag_count AS tc, branch_count AS bc, commit_count AS cc
		FROM symbol


	    } {
		$mysymbol map $sid [list $pid $name]
		set project $myprojmap($pid)

		set force  [$project hassymbol $name]
		set symbol [$project getsymbol $name]

		# Forcing happens only for the trunks.
................................................................................

		# future: $symbol load (blockers, and parents)
	    }

	    # Beyond the symbols we also load the author, commit log,
	    # and meta information.

	    state foreachrow {
		SELECT aid, name AS aname FROM author
	    } {
		$myauthor map $aid $aname
	    }
	    state foreachrow {
		SELECT cid, text FROM cmessage
	    } {
		$mycmsg map $cid $text
	    }
	    state foreachrow {
		SELECT mid, pid, bid, aid, cid FROM meta
	    } {
		$mymeta map $mid [list $pid $bid $aid $cid]
	    }
	}
	return
    }

    typemethod determinesymboltypes {} {