Fossil

Check-in [3c0ef2c3]
Login

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

Overview
Comment:Removed lots of now dead code. Added a note to the last remaining user of the changeset method 'nextmap'.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:3c0ef2c3799a576cd72e0240545289d6e383225e
User & Date: aku 2007-12-05 02:21:00
Context
2007-12-05
02:22
The handling of detached lines of development (floating branches) still had some bugs regarding the linkage to their revisions, especially the first revision on such branches. Fixed the relevant places, added early integrity checks and updated the main checks to handle the situation. check-in: c4003e7b user: aku tags: trunk
02:21
Removed lots of now dead code. Added a note to the last remaining user of the changeset method 'nextmap'. check-in: 3c0ef2c3 user: aku tags: trunk
2007-12-04
04:54
Reworked ComputeLimits in the last breaker pass. Moved the heavy computation of the max predecessor / min successor data down to the sql in the changeset class. check-in: 711e0002 user: aku tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

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

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
174
175
176
177
178
179
180
181
182
183
184
185
...
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
....
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
....
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
....
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
	return [struct::list map [state run {
	    SELECT S.nid
	    FROM   cssuccessor S
	    WHERE  S.cid = $myid
	}] [mytypemethod of]]
    }

    # result = dict (item -> list (changeset))
    method successormap {} {
	# NOTE / FUTURE: Definitive bottleneck (can be millions of pairs).
	#
	# Only user is pass 9, computing the limits of backward
	# branches per branch in the changeset. TODO: Fold that into
	# the SQL query, i.e. move the crunching from Tcl to C.

	array set tmp {}
	foreach {rev children} [$self nextmap] {
	    foreach child $children {
		lappend tmp($rev) $myitemmap($child)
	    }
	    set tmp($rev) [lsort -unique $tmp($rev)]
	}
	return [array get tmp]
    }

    # result = dict (item -> list (changeset))
    method predecessormap {} {
	# NOTE / FUTURE: Definitive bottleneck (can be millions of pairs).
	#
	# Only user is pass 9, computing the limits of backward
	# branches per branch in the changeset. TODO: Fold that into
	# the SQL query, i.e. move the crunching from Tcl to C.

	array set tmp {}
	foreach {rev children} [$self premap] {
	    foreach child $children {
		lappend tmp($rev) $myitemmap($child)
	    }
	    set tmp($rev) [lsort -unique $tmp($rev)]
	}
	return [array get tmp]
    }

    # item -> list (item)
    method nextmap {} {
	#if {[llength $mynextmap]} { return $mynextmap }
	$mytypeobj successors tmp $myitems
	return [array get tmp]
	#set mynextmap [array get tmp]
	#return $mynextmap
    }

    # item -> list (item)
    method premap {} {
	#if {[llength $mypremap]} { return $mypremap }
	$mytypeobj predecessors tmp $myitems
	return [array get tmp]
	#set mypremap [array get tmp]
	#return $mypremap
    }

    method breakinternaldependencies {} {

	##
	## NOTE: This method, maybe in conjunction with its caller
	##       seems to be a memory hog, especially for large
................................................................................
			      # mytype.
    variable mysrcid     {} ; # Id of the metadata or symbol the cset
			      # is based on.
    variable myitems     {} ; # List of the file level revisions,
			      # tags, or branches in the cset, as
			      # ids. Not tagged.
    variable mytitems    {} ; # As myitems, the tagged form.
    variable mypremap    {} ; # Dictionary mapping from the items (tagged now)
			      # to their predecessors, also tagged. A
			      # cache to avoid loading this from the
			      # state more than once.
    variable mynextmap   {} ; # Dictionary mapping from the items (tagged)
			      # to their successors (also tagged). A
			      # cache to avoid loading this from the
			      # state more than once.
    variable mypos       {} ; # Commit position of the changeset, if
			      # known.

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

    typevariable mycounter        0 ; # Id counter for csets. Last id
................................................................................
	    AND    B.root = R.rid
	"] {
	    lappend dependencies([list rev $rid]) [list sym::branch $child]
	}
	return
    }

    # var(dv) = dict (item -> list (item)), item  = list (type id)
    typemethod predecessors {dv revisions} {
	upvar 1 $dv dependencies
	set theset ('[join $revisions {','}]')

	# The following cases specify when a revision P is a
	# predecessor of a revision R. Each of the cases translates
	# into one of the branches of the SQL UNION coming below.
	#
	# (1) The immediate parent R.parent of R is a predecessor of
	#     R. NOTE: This is true for R either primary or secondary
	#     child of P. It not necessary to distinguish the two
	#     cases, in contrast to the code retrieving the successor
	#     information.
	#
	# (2) The complement of successor case (3). The trunk root is
	#     a predecessor of a NTDB root. REMOVED. See 'successors'
	#     for the explanation.
	#
	# (3) The complement of successor case (4). The last NTDB
	#     revision belonging to the trunk is a predecessor of the
	#     primary child of the trunk root (The '1.2' revision).

	foreach {rid parent} [state run "
   -- (1) Primary parent, can be in different LOD for first in a branch
	    SELECT R.rid, R.parent
	    FROM   revision R
	    WHERE  R.rid   IN $theset     -- Restrict to revisions of interest
	    AND    R.parent IS NOT NULL   -- Has primary parent
    UNION
    -- (3) Last NTDB on trunk is predecessor of child of trunk root
	    SELECT R.rid, RA.dbparent
	    FROM   revision R, revision RA
	    WHERE  R.rid IN $theset         -- Restrict to revisions of interest
	    AND    NOT R.isdefault          -- not on NTDB
	    AND    R.parent IS NOT NULL     -- which are not root
	    AND    RA.rid = R.parent        -- go to their parent
	    AND    RA.dbparent IS NOT NULL  -- which has to refer to NTDB's root
	"] {
	    # Consider moving this to the integrity module.
	    integrity assert {$rid != $parent} {Revision $rid depends on itself.}
	    lappend dependencies([list rev $rid]) [list rev $parent]
	}

	# The revisions which are the first on a branch have that
	# branch as their predecessor. Note that revisions cannot be
	# on tags in the same manner, so tags cannot be predecessors
	# of revisions. This complements that they have no successors
	# (See sym::tag/successors).

	foreach {rid parent} [state run "
	    SELECT R.rid, B.bid
	    FROM   revision R, branch B
	    WHERE  R.rid IN $theset
	    AND    B.first = R.rid
	"] {
	    lappend dependencies([list rev $rid]) [list sym::branch $parent]
	}
	return
    }

    # result = list (changeset-id)
    typemethod cs_successors {revisions} {
        # This is a variant of 'successors' which maps the low-level
        # data directly to the associated changesets. I.e. instead
        # millions of dependency pairs (in extreme cases (Example: Tcl
        # CVS)) we return a very short and much more manageable list
        # of changesets.
................................................................................

    # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
    typemethod loops {tags} {
	# Tags have no successors, therefore cannot cause loops
	return {}
    }

    # var(dv) = dict (item -> list (item)), item  = list (type id)
    typemethod predecessors {dv tags} {
	upvar 1 $dv dependencies
	# The predecessors of a tag are all the revisions the tags are
	# attached to, as well as all the branches or tags which are
	# their prefered parents.

	set theset ('[join $tags {','}]')
	foreach {tid parent} [state run "
	    SELECT T.tid, R.rid
	    FROM   tag T, revision R
	    WHERE  T.tid IN $theset
	    AND    T.rev = R.rid
	"] {
	    lappend dependencies([list sym::tag $tid]) [list rev $parent]
	}

	foreach {tid parent} [state run "
	    SELECT T.tid, B.bid
	    FROM   tag T, preferedparent P, branch B
	    WHERE  T.tid IN $theset
	    AND    T.sid = P.sid
	    AND    P.pid = B.sid
	"] {
	    lappend dependencies([list sym::tag $tid]) [list sym::branch $parent]
	}

	foreach {tid parent} [state run "
	    SELECT T.tid, TX.tid
	    FROM   tag T, preferedparent P, tag TX
	    WHERE  T.tid IN $theset
	    AND    T.sid = P.sid
	    AND    P.pid = TX.sid
	"] {
	    lappend dependencies([list sym::tag $tid]) [list sym::tag $parent]
	}
	return
    }

    # result = list (changeset-id)
    typemethod cs_successors {tags} {
	# Tags have no successors.
	return
    }
}

................................................................................
	    FROM   branch B, preferedparent P, tag T
	    WHERE  B.bid IN $theset
	    AND    B.sid = P.pid
	    AND    T.sid = P.sid
	"] {
	    lappend dependencies([list sym::branch $bid]) [list sym::tag $child]
	}
	return
    }

    # var(dv) = dict (item -> list (item)), item  = list (type id)
    typemethod predecessors {dv branches} {
	upvar 1 $dv dependencies
	# The predecessors of a branch are all the revisions the
	# branches are spawned from, as well as all the branches or
	# tags which are their prefered parents.

	set theset ('[join $branches {','}]')
	foreach {bid parent} [state run "
	    SELECT B.Bid, R.rid
	    FROM   branch B, revision R
	    WHERE  B.bid IN $theset
	    AND    B.root = R.rid
	"] {
	    lappend dependencies([list sym::branch $bid]) [list rev $parent]
	}
	foreach {bid parent} [state run "
	    SELECT B.bid, BX.bid
	    FROM   branch B, preferedparent P, branch BX
	    WHERE  B.bid IN $theset
	    AND    B.sid = P.sid
	    AND    P.pid = BX.sid
	"] {
	    lappend dependencies([list sym::branch $bid]) [list sym::branch $parent]
	}
	foreach {bid parent} [state run "
	    SELECT B.bid, T.tid
	    FROM   branch B, preferedparent P, tag T
	    WHERE  B.bid IN $theset
	    AND    B.sid = P.sid
	    AND    P.pid = T.sid
	"] {
	    lappend dependencies([list sym::branch $bid]) [list sym::tag $parent]
	}
	return
    }

    # result = list (changeset-id)
    typemethod cs_successors {branches} {
        # This is a variant of 'successors' which maps the low-level
        # data directly to the associated changesets. I.e. instead







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


<


<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







120
121
122
123
124
125
126




































127
128

129
130











131
132
133
134
135
136
137
...
526
527
528
529
530
531
532








533
534
535
536
537
538
539
....
1036
1037
1038
1039
1040
1041
1042





























































1043
1044
1045
1046
1047
1048
1049
....
1139
1140
1141
1142
1143
1144
1145







































1146
1147
1148
1149
1150
1151
1152
....
1236
1237
1238
1239
1240
1241
1242





































1243
1244
1245
1246
1247
1248
1249
	return [struct::list map [state run {
	    SELECT S.nid
	    FROM   cssuccessor S
	    WHERE  S.cid = $myid
	}] [mytypemethod of]]
    }





































    # item -> list (item)
    method nextmap {} {

	$mytypeobj successors tmp $myitems
	return [array get tmp]











    }

    method breakinternaldependencies {} {

	##
	## NOTE: This method, maybe in conjunction with its caller
	##       seems to be a memory hog, especially for large
................................................................................
			      # mytype.
    variable mysrcid     {} ; # Id of the metadata or symbol the cset
			      # is based on.
    variable myitems     {} ; # List of the file level revisions,
			      # tags, or branches in the cset, as
			      # ids. Not tagged.
    variable mytitems    {} ; # As myitems, the tagged form.








    variable mypos       {} ; # Commit position of the changeset, if
			      # known.

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

    typevariable mycounter        0 ; # Id counter for csets. Last id
................................................................................
	    AND    B.root = R.rid
	"] {
	    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
        # data directly to the associated changesets. I.e. instead
        # millions of dependency pairs (in extreme cases (Example: Tcl
        # CVS)) we return a very short and much more manageable list
        # of changesets.
................................................................................

    # result = 4-list (itemtype itemid nextitemtype nextitemid ...)
    typemethod loops {tags} {
	# Tags have no successors, therefore cannot cause loops
	return {}
    }








































    # result = list (changeset-id)
    typemethod cs_successors {tags} {
	# Tags have no successors.
	return
    }
}

................................................................................
	    FROM   branch B, preferedparent P, tag T
	    WHERE  B.bid IN $theset
	    AND    B.sid = P.pid
	    AND    T.sid = P.sid
	"] {
	    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
        # data directly to the associated changesets. I.e. instead

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

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
..
67
68
69
70
71
72
73




74
75
76
77
78
79
80
	# four categories.

	# 1. Revisions whose predecessors are not in PREV, nor are
	#    their successors found in NEXT. These revisions do not
	#    count, as they did not induce any of the two dependencies
	#    under consideration. They can be ignored.

	# 2. Revisions which have predecessors in PREV and sucessors
	#    in NEXT. They are called 'passthrough' in cvs2svn. They
	#    induce both dependencies under consideration and are thus
	#    critical in the creation of the cycle. As such they are
	#    also unbreakable :(

	# 3. Revisions which have predecessor in PREVE, but no
	#    successors in NEXT. As such they induced the incoming
................................................................................
	#    dependency, but not the incoming one.

	# If we have no passthrough revisions then splitting the
	# changeset between categories 3 and 4, with category 1 going
	# wherever, will break the cycle. If category 2 revisions are
	# present we can still perform the split, this will however
	# not break the cycle, only weaken it.





	array set csetprevmap [Invert [$myprev nextmap]]
	array set csetnextmap [$mycset nextmap]

	set prevrev [$myprev items]
	set nextrev [$mynext items]








|







 







>
>
>
>







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
..
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
	# four categories.

	# 1. Revisions whose predecessors are not in PREV, nor are
	#    their successors found in NEXT. These revisions do not
	#    count, as they did not induce any of the two dependencies
	#    under consideration. They can be ignored.

	# 2. Revisions which have predecessors in PREV and successors
	#    in NEXT. They are called 'passthrough' in cvs2svn. They
	#    induce both dependencies under consideration and are thus
	#    critical in the creation of the cycle. As such they are
	#    also unbreakable :(

	# 3. Revisions which have predecessor in PREVE, but no
	#    successors in NEXT. As such they induced the incoming
................................................................................
	#    dependency, but not the incoming one.

	# If we have no passthrough revisions then splitting the
	# changeset between categories 3 and 4, with category 1 going
	# wherever, will break the cycle. If category 2 revisions are
	# present we can still perform the split, this will however
	# not break the cycle, only weaken it.

	# NOTE: This is the only remaining user of 'nextmap'. Look
	# into the possibility of performing the relevant counting
	# within the database.

	array set csetprevmap [Invert [$myprev nextmap]]
	array set csetnextmap [$mycset nextmap]

	set prevrev [$myprev items]
	set nextrev [$mynext items]