The MinGW.org Installation Manager Tool
Révision | e15828a255b9c4ad23b572ba115f125c6ab797f5 (tree) |
---|---|
l'heure | 2011-10-05 06:07:32 |
Auteur | Keith Marshall <keithmarshall@user...> |
Commiter | Keith Marshall |
Establish mapping from release tarname to source tarname.
@@ -1,3 +1,16 @@ | ||
1 | +2011-10-04 Keith Marshall <keithmarshall@users.sourceforge.net> | |
2 | + | |
3 | + Establish mapping from release tarname to source tarname. | |
4 | + | |
5 | + * src/pkgreqs.cpp (inherited_requirement): New inline function. | |
6 | + (requirement): Use it; adapt to propagate release archive format and | |
7 | + compression type fields, in addition to version fields, when resolving | |
8 | + "%" wildcard matches within the template for the resultant tarname. | |
9 | + (pkgAssociateName): New public function; implement it for use by... | |
10 | + * src/pkgname.cpp (pkgResolvedName): ...this new inline function. | |
11 | + (pkgXmlNode::SourceArchiveName): Use it; adapt to accept a category | |
12 | + selector, so it may resolve source or licence tarnames on demand. | |
13 | + | |
1 | 14 | 2011-10-02 Keith Marshall <keithmarshall@users.sourceforge.net> |
2 | 15 | |
3 | 16 | Facilitate downloads using diverse cache directories. |
@@ -4,7 +4,7 @@ | ||
4 | 4 | * $Id$ |
5 | 5 | * |
6 | 6 | * Written by Keith Marshall <keithmarshall@users.sourceforge.net> |
7 | - * Copyright (C) 2009, 2010, MinGW Project | |
7 | + * Copyright (C) 2009, 2010, 2011, MinGW Project | |
8 | 8 | * |
9 | 9 | * |
10 | 10 | * Implementation for the non-inherited components of the pkgXmlNode |
@@ -33,6 +33,8 @@ | ||
33 | 33 | #include "dmh.h" |
34 | 34 | #include "pkgbase.h" |
35 | 35 | #include "pkgkeys.h" |
36 | +#include "pkginfo.h" | |
37 | +#include "pkgtask.h" | |
36 | 38 | |
37 | 39 | static |
38 | 40 | const char *pkgArchiveName( pkgXmlNode *rel, const char *tag, unsigned opt ) |
@@ -133,7 +135,147 @@ const char *pkgArchiveName( pkgXmlNode *rel, const char *tag, unsigned opt ) | ||
133 | 135 | return (opt || matched) ? rel->GetPropVal( tarname_key, NULL ) : NULL; |
134 | 136 | } |
135 | 137 | |
136 | -const char *pkgXmlNode::SourceArchiveName() | |
138 | +EXTERN_C const char *pkgAssociateName( const char *, const char * ); | |
139 | + | |
140 | +static inline | |
141 | +const char *pkgResolvedName( pkgXmlNode *rel, const char *tag, const char *ext ) | |
142 | +{ | |
143 | + /* Local helper function to resolve the mapping from a released | |
144 | + * package name, as identified from the XML release element "rel", | |
145 | + * to its corresponding source or licence package name, according | |
146 | + * to the selection of "source" or "licence" specified by "tag", | |
147 | + * with "ext" passed a "src" or "lic" respectively. | |
148 | + */ | |
149 | + const char *refname; | |
150 | + const char *retname = NULL; | |
151 | + | |
152 | + /* First, we retrieve the released package name... | |
153 | + */ | |
154 | + if( (refname = pkgArchiveName( rel, release_key, 1 )) != NULL ) | |
155 | + { | |
156 | + /* ...and if successful, look for an explicit reference to | |
157 | + * the source or licence package, embedded within the release | |
158 | + * specification itself. | |
159 | + */ | |
160 | + if( (retname = pkgArchiveName( rel, tag, 0 )) == NULL ) | |
161 | + { | |
162 | + /* When this fails to identify the required mapping, | |
163 | + * then we look for a generic reference, defined for | |
164 | + * the containing package. | |
165 | + */ | |
166 | + pkgXmlNode *enc = rel->GetParent(); | |
167 | + | |
168 | + /* A generic reference may be placed at any nesting | |
169 | + * level, between the enclosing package element and | |
170 | + * the release to which it relates; thus, starting | |
171 | + * at the first enclosing level... | |
172 | + */ | |
173 | + rel = NULL; | |
174 | + while( enc != NULL ) | |
175 | + { | |
176 | + /* ...enumerate reference specifications of the | |
177 | + * appropriate type, examining all children of | |
178 | + * the enclosing element. | |
179 | + */ | |
180 | + unsigned matched = 0; | |
181 | + pkgXmlNode *child = enc->GetChildren(); | |
182 | + while( child != NULL ) | |
183 | + { | |
184 | + /* We have a child, which we have not examined... | |
185 | + */ | |
186 | + if( child->IsElementOfType( tag ) ) | |
187 | + { | |
188 | + /* ...and it is of the required "tag" type. | |
189 | + */ | |
190 | + if( matched++ ) | |
191 | + /* | |
192 | + * We already had a candidate match, so we | |
193 | + * diagnose but otherwise this duplicate... | |
194 | + */ | |
195 | + dmh_notify( DMH_WARNING, | |
196 | + "redundant %s specification ignored\n", tag | |
197 | + ); | |
198 | + | |
199 | + else | |
200 | + /* This is the first candidate match found, | |
201 | + * so we accept it. | |
202 | + */ | |
203 | + rel = child; | |
204 | + } | |
205 | + /* Continue examining child elements, until no more | |
206 | + * are present at the current nesting level. | |
207 | + */ | |
208 | + child = child->GetNext(); | |
209 | + } | |
210 | + | |
211 | + /* When we've completed the examination of all children | |
212 | + * at a given nesting level, without finding a matching | |
213 | + * specification, and that level is still within the | |
214 | + * enclosing package element... | |
215 | + */ | |
216 | + if( (rel == NULL) && ! enc->IsElementOfType( package_key ) ) | |
217 | + /* | |
218 | + * ...then we extend the search to the next enclosing | |
219 | + * level of nesting... | |
220 | + */ | |
221 | + enc = enc->GetParent(); | |
222 | + | |
223 | + else | |
224 | + /* ...otherwise, we abandon the search. | |
225 | + */ | |
226 | + enc = NULL; | |
227 | + } | |
228 | + | |
229 | + /* If we've searched all available nesting levels, | |
230 | + * and failed to locate the requisite specification... | |
231 | + */ | |
232 | + if( rel == NULL ) | |
233 | + { | |
234 | + /* ...then we assume that the requisite tarname | |
235 | + * is identical to the release tarname, with the | |
236 | + * appropriate "ext" substitution for the package | |
237 | + * class identification... | |
238 | + */ | |
239 | + pkgSpecs resolved( refname ); | |
240 | + resolved.SetComponentClass( ext ); | |
241 | + /* | |
242 | + * ...so, having made the substitution, | |
243 | + * we return the resultant tarname, noting | |
244 | + * that this automatically allocates space | |
245 | + * on the heap, for the returned string. | |
246 | + */ | |
247 | + return resolved.GetTarName(); | |
248 | + } | |
249 | + else | |
250 | + /* We did find a mappingspecification, so we | |
251 | + * extract a tarname template from it. | |
252 | + */ | |
253 | + retname = rel->GetPropVal( tarname_key, NULL ); | |
254 | + } | |
255 | + else if( strcmp( retname, value_none ) == 0 ) | |
256 | + /* | |
257 | + * The package is virtual, or an explicit mapping | |
258 | + * specification indicates that there is no related | |
259 | + * source or licence package; return NULL to advise | |
260 | + * the caller of this. | |
261 | + */ | |
262 | + return NULL; | |
263 | + | |
264 | + /* If we get to here, we found a mapping specification; | |
265 | + * it may be a template, so resolve any substitutions which | |
266 | + * it must inherit from the released package tarname, again | |
267 | + * noting that this allocates heap memory for the result. | |
268 | + */ | |
269 | + retname = pkgAssociateName( retname, refname ); | |
270 | + } | |
271 | + | |
272 | + /* Finally, how ever we resolved the mapping, we return | |
273 | + * the result. | |
274 | + */ | |
275 | + return retname; | |
276 | +} | |
277 | + | |
278 | +const char *pkgXmlNode::SourceArchiveName( unsigned long category ) | |
137 | 279 | { |
138 | 280 | /* Applicable only for XML nodes designated as "release". |
139 | 281 | * |
@@ -146,7 +288,22 @@ const char *pkgXmlNode::SourceArchiveName() | ||
146 | 288 | * not represent a "release", or if it does not have a contained |
147 | 289 | * "source" element specifying a "tarname" property. |
148 | 290 | */ |
149 | - return pkgArchiveName( this, source_key, 0 ); | |
291 | + const char *tag = "lic"; | |
292 | + if( category != ACTION_LICENCE ) | |
293 | + { | |
294 | + /* We may have been asked to explicitly override the "source" | |
295 | + * mapping, returning the "licence" reference instead; where | |
296 | + * this special exception is NOT requested, then we enforce | |
297 | + * the default case. | |
298 | + */ | |
299 | + category = ACTION_SOURCE; | |
300 | + tag = "src"; | |
301 | + } | |
302 | + | |
303 | + /* In either case, pkgResolvedName() determines the appropriate | |
304 | + * archive name, which it automatically returns on the heap. | |
305 | + */ | |
306 | + return pkgResolvedName( this, action_name( category ), tag ); | |
150 | 307 | } |
151 | 308 | |
152 | 309 | const char *pkgXmlNode::ArchiveName() |
@@ -327,6 +327,16 @@ enum inherit_mode | ||
327 | 327 | INHERIT_ALL /* "%" matches the entire version string */ |
328 | 328 | }; |
329 | 329 | |
330 | +static inline | |
331 | +bool inherited_requirement( const char *field ) | |
332 | +{ | |
333 | + /* Local helper function to identify a template field which is | |
334 | + * specified exactly as "%", and therefore must inherit its value | |
335 | + * from the referring package specification. | |
336 | + */ | |
337 | + return ((field != NULL) && (field[0] == '%') && (field[1] == '\0')); | |
338 | +} | |
339 | + | |
330 | 340 | static |
331 | 341 | enum inherit_mode inherited( const char *ver, const char *bld ) |
332 | 342 | { |
@@ -341,7 +351,7 @@ enum inherit_mode inherited( const char *ver, const char *bld ) | ||
341 | 351 | /* Noting that the "%" wildcard must represent the respective part |
342 | 352 | * of the version specification in its entirety... |
343 | 353 | */ |
344 | - if( (ver != NULL) && (ver[0] == '%') && (ver[1] == '\0') ) | |
354 | + if( inherited_requirement( ver ) ) | |
345 | 355 | /* |
346 | 356 | * ...flag a match on the "major.minor.patch" specification. |
347 | 357 | */ |
@@ -434,6 +444,18 @@ const char *requirement( const char *wanted, pkgSpecs *dep ) | ||
434 | 444 | */ |
435 | 445 | id.SetSubSystemBuild( dep->GetSubSystemBuild() ); |
436 | 446 | |
447 | + /* To establish association between source and binary package names, | |
448 | + * we may also need to propagate archive and compression type fields... | |
449 | + */ | |
450 | + if( inherited_requirement( id.GetPackageFormat()) ) | |
451 | + { | |
452 | + id.SetPackageFormat( dep->GetPackageFormat() ); | |
453 | + if( id.GetCompressionType() == NULL ) | |
454 | + id.SetCompressionType( dep->GetCompressionType() ); | |
455 | + } | |
456 | + else if( inherited_requirement( id.GetCompressionType()) ) | |
457 | + id.SetCompressionType( dep->GetCompressionType() ); | |
458 | + | |
437 | 459 | /* Finally, reconstitute the canonical tarname representation of the |
438 | 460 | * specification, from its decomposed representation; (as a side effect, |
439 | 461 | * this automatically places the return string on the heap). |
@@ -507,4 +529,14 @@ const char * pkgActionItem::SetRequirements( pkgXmlNode *req, pkgSpecs *dep ) | ||
507 | 529 | return (min_wanted == NULL) ? max_wanted : min_wanted; |
508 | 530 | } |
509 | 531 | |
532 | +EXTERN_C const char *pkgAssociateName( const char *map, const char *from ) | |
533 | +{ | |
534 | + /* Public function for derivation of the name of an associate package, | |
535 | + * such as a source package, from the name of the primary package, based | |
536 | + * on the relationship specified by the template passed via "map". | |
537 | + */ | |
538 | + pkgSpecs ref( from ); | |
539 | + return requirement( map, &ref ); | |
540 | +} | |
541 | + | |
510 | 542 | /* $RCSfile$: end of file */ |