File: c2f_pcollsym.tcl

package info (click to toggle)
fossil 1%3A1.22.1%2Bdfsg-0.1
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 10,588 kB
  • sloc: ansic: 151,799; tcl: 10,291; sh: 4,413; makefile: 1,822; sql: 376
file content (318 lines) | stat: -rw-r--r-- 10,211 bytes parent folder | download | duplicates (9)
1
2
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
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
259
260
261
262
263
264
265
266
267
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
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
## -*- tcl -*-
# # ## ### ##### ######## ############# #####################
## Copyright (c) 2007 Andreas Kupries.
#
# This software is licensed as described in the file LICENSE, which
# you should have received as part of this distribution.
#
# This software consists of voluntary contributions made by many
# individuals.  For exact contribution history, see the revision
# history and logs, available at http://fossil-scm.hwaci.com/fossil
# # ## ### ##### ######## ############# #####################

## Pass III. This pass divides the symbols collected by the previous
## pass into branches, tags, and excludes. The latter are also
## partially deleted by this pass, not only marked. It is the next
## pass however, 'FilterSym', which performs the full deletion.

# # ## ### ##### ######## ############# #####################
## Requirements

package require Tcl 8.4                               ; # Required runtime.
package require snit                                  ; # OO system.
package require vc::tools::trouble                    ; # Error reporting.
package require vc::tools::log                        ; # User feedback.
package require vc::fossil::import::cvs::repository   ; # Repository management.
package require vc::fossil::import::cvs::state        ; # State storage.
package require vc::fossil::import::cvs::project::sym ; # Project level symbols

# # ## ### ##### ######## ############# #####################
## Register the pass with the management

vc::fossil::import::cvs::pass define \
    CollateSymbols \
    {Collate symbols} \
    ::vc::fossil::import::cvs::pass::collsym

# # ## ### ##### ######## ############# #####################
##

snit::type ::vc::fossil::import::cvs::pass::collsym {
    # # ## ### ##### ######## #############
    ## Public API

    typemethod setup {} {
	# Define names and structure of the persistent state of this
	# pass.

	state use project
	state use symbol
	state use symtype
	state use blocker
	state use parent

	state extend preferedparent {
	    -- For each symbol the prefered parent. This describes the
	    -- tree of the found lines of development. Actually a
	    -- forest in case of multiple projects, with one tree per
	    -- project.

	    sid INTEGER  NOT NULL  PRIMARY KEY  REFERENCES symbol,
	    pid INTEGER  NOT NULL               REFERENCES symbol
	} { pid }
	# Index on: pid (branch successors)
	return
    }

    typemethod load {} {
	# Pass manager interface. Executed to load data computed by
	# this pass into memory when this pass is skipped instead of
	# executed.

	# The results of this pass are fully in the persistent state,
	# there is nothing to load for the next one.
	return
    }

    typemethod run {} {
	# Pass manager interface. Executed to perform the
	# functionality of the pass.

	state transaction {
	    repository   determinesymboltypes

	    project::sym printrulestatistics
	    project::sym printtypestatistics
	}

	if {![trouble ?]} {
	    UnconvertedSymbols
	    BadSymbolTypes
	    BlockedExcludes
	    InvalidTags
	}

	if {![trouble ?]} {
	    DropExcludedSymbolsFromReferences
	    DeterminePreferedParents
	}

	log write 1 collsym "Collation completed"
	return
    }

    typemethod discard {} {
	# Pass manager interface. Executed for all passes after the
	# run passes, to remove all data of this pass from the state,
	# as being out of date.

	state discard preferedparent
	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
	# which absolutely cannot be converted as tags due to commits
	# made on them ?

	# 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
	# possible parent for other symbols. We now drop the relevant
	# entries to prevent them from causing confusion later on.

	set excl [project::sym excluded]

	state run {
	    DELETE FROM blocker
	    WHERE bid IN (SELECT sid
			  FROM   symbol
			  WhERE  type = $excl); -- Get excluded symbols
	    DELETE FROM parent
	    WHERE pid IN (SELECT sid
			  FROM   symbol
			  WhERE  type = $excl); -- Get excluded symbols
	}
	return
    }

    proc DeterminePreferedParents {} {
	array set prefered {}

	set excl [project::sym excluded]

	# Phase I: Pull the possible parents, using sorting to put the
	#          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 symbols,
	#          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
	    state run {
		INSERT INTO preferedparent (sid, pid)
		VALUES                     ($s,  $p);
	    }

	    log write 3 pcollsym "$prname : '$sname's prefered parent is '$pname'"
	}

	# 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
    }

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

    pragma -hasinstances   no ; # singleton
    pragma -hastypeinfo    no ; # no introspection
    pragma -hastypedestroy no ; # immortal

    # # ## ### ##### ######## #############
}

namespace eval ::vc::fossil::import::cvs::pass {
    namespace export collsym
    namespace eval collsym {
	namespace import ::vc::fossil::import::cvs::repository
	namespace import ::vc::fossil::import::cvs::state
	namespace eval project {
	    namespace import ::vc::fossil::import::cvs::project::sym
	}
	namespace import ::vc::tools::trouble
	namespace import ::vc::tools::log
	log register collsym
    }
}

# # ## ### ##### ######## ############# #####################
## Ready

package provide vc::fossil::import::cvs::pass::collsym 1.0
return