6 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
7 * Copyright (C) 2009, 2010, 2011, MinGW Project
10 * Implementation for the non-inherited components of the pkgXmlNode
11 * class, as declared in file "pkgdesc.h"; fundamentally, these are
12 * the accessors for package "tarname" properties, as specified in
13 * XML nodes identified as "release" elements.
16 * This is free software. Permission is granted to copy, modify and
17 * redistribute this software, under the provisions of the GNU General
18 * Public License, Version 3, (or, at your option, any later version),
19 * as published by the Free Software Foundation; see the file COPYING
20 * for licensing details.
22 * Note, in particular, that this software is provided "as is", in the
23 * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not
24 * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY
25 * PARTICULAR PURPOSE. Under no circumstances will the author, or the
26 * MinGW Project, accept liability for any damages, however caused,
27 * arising from the use of this software.
40 const char *pkgArchiveName( pkgXmlNode *rel, const char *tag, unsigned opt )
42 /* Local helper to establish actual release file names...
43 * applicable only to XML "release" elements.
45 if( ! rel->IsElementOfType( release_key ) )
47 /* The XML element type name is not "release"; identify it...
50 if( (reftype = rel->GetName()) == NULL )
52 * ...or classify as "unknown", when given a NULL element.
54 reftype = value_unknown;
56 /* Complain that this XML element type is invalid, in this context...
58 dmh_control( DMH_BEGIN_DIGEST );
59 dmh_notify( DMH_ERROR, "internal package specification error\n" );
60 dmh_notify( DMH_ERROR, "can't get 'tarname' for non-release element %s\n", reftype );
61 dmh_notify( DMH_ERROR, "please report this to the package maintainer\n" );
62 dmh_control( DMH_END_DIGEST );
64 /* ...and bail out, telling the caller that no archive name is available...
69 /* Given a package release specification...
70 * First check that it relates to a real package, rather than to
71 * a virtual "meta-package"; such meta-packages exist solely as
72 * containers for requirements specifications, and have no
75 pkgXmlNode *pkg = rel->GetParent();
76 while( (pkg != NULL) && ! pkg->IsElementOfType( package_key ) )
77 pkg = pkg->GetParent();
79 /* FIXME: we should probably provide some error handling here,
80 * to diagnose release elements without any package association;
81 * (these would be identified by pkg == NULL).
85 /* We found the package association...
86 * Check its 'class' attribute, if any, and if classified as
87 * 'virtual', return the archive association as "none".
89 const char *package_class = pkg->GetPropVal( class_key, NULL );
90 if( (package_class != NULL) && (strcmp( package_class, value_virtual ) == 0) )
94 /* The given release specification relates to a real package...
95 * Determine the archive name for the tarball to be processed; this
96 * is retrieved from a child XML element with name specified by "tag";
97 * by default, if "opt" is non-zero, it is the canonical "tarname"
98 * assigned to the release element itself, unless an alternative
99 * specification is provided; if "opt" is zero, no default is
100 * assumed, and the return value is NULL if no alternative
101 * specification is provided.
103 unsigned matched = 0;
104 pkgXmlNode *dl = rel->GetChildren();
107 /* Visit all children of the release specification element,
108 * checking for the presence of an expected specification...
110 if( dl->IsElementOfType( tag ) )
112 /* Found one; ensure it is the only one...
116 * ...else emit a warning, and ignore this one...
118 dmh_notify( DMH_WARNING, "%s: archive name reassignment ignored\n",
119 rel->GetPropVal( tarname_key, value_unknown )
122 /* ...ok; this is the first "tag" specification,
123 * accept it as the non-default source of the release's
124 * "tarname" property.
128 /* Continue, until all children have been visited.
132 /* "rel" now points to the XML element having the appropriate
133 * "tarname" specification; return a pointer to it's value.
135 return (opt || matched) ? rel->GetPropVal( tarname_key, NULL ) : NULL;
138 EXTERN_C const char *pkgAssociateName( const char *, const char * );
141 const char *pkgResolvedName( pkgXmlNode *rel, const char *tag, const char *ext )
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.
150 const char *retname = NULL;
152 /* First, we retrieve the released package name...
154 if( (refname = pkgArchiveName( rel, release_key, 1 )) != NULL )
156 /* ...and if successful, look for an explicit reference to
157 * the source or licence package, embedded within the release
158 * specification itself.
160 if( (retname = pkgArchiveName( rel, tag, 0 )) == NULL )
162 /* When this fails to identify the required mapping,
163 * then we look for a generic reference, defined for
164 * the containing package.
166 pkgXmlNode *enc = rel->GetParent();
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...
176 /* ...enumerate reference specifications of the
177 * appropriate type, examining all children of
178 * the enclosing element.
180 unsigned matched = 0;
181 pkgXmlNode *child = enc->GetChildren();
182 while( child != NULL )
184 /* We have a child, which we have not examined...
186 if( child->IsElementOfType( tag ) )
188 /* ...and it is of the required "tag" type.
192 * We already had a candidate match, so we
193 * diagnose but otherwise this duplicate...
195 dmh_notify( DMH_WARNING,
196 "redundant %s specification ignored\n", tag
200 /* This is the first candidate match found,
205 /* Continue examining child elements, until no more
206 * are present at the current nesting level.
208 child = child->GetNext();
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...
216 if( (rel == NULL) && ! enc->IsElementOfType( package_key ) )
218 * ...then we extend the search to the next enclosing
219 * level of nesting...
221 enc = enc->GetParent();
224 /* ...otherwise, we abandon the search.
229 /* If we've searched all available nesting levels,
230 * and failed to locate the requisite specification...
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...
239 pkgSpecs resolved( refname );
240 resolved.SetComponentClass( ext );
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.
247 return resolved.GetTarName();
250 /* We did find a mappingspecification, so we
251 * extract a tarname template from it.
253 retname = rel->GetPropVal( tarname_key, NULL );
255 else if( strcmp( retname, value_none ) == 0 )
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.
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.
269 retname = pkgAssociateName( retname, refname );
272 /* Finally, how ever we resolved the mapping, we return
278 const char *pkgXmlNode::SourceArchiveName( unsigned long category )
280 /* Applicable only for XML nodes designated as "release".
282 * Retrieve the source tarball name, if specified, from the
283 * "tarname" property of the contained "source" element, within
284 * an XML node designated as a "release" element.
286 * Returns a pointer to the text of the "tarname" property of the
287 * contained "source" element, or NULL if the containing node does
288 * not represent a "release", or if it does not have a contained
289 * "source" element specifying a "tarname" property.
291 const char *tag = "lic";
292 if( category != ACTION_LICENCE )
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
299 category = ACTION_SOURCE;
303 /* In either case, pkgResolvedName() determines the appropriate
304 * archive name, which it automatically returns on the heap.
306 return pkgResolvedName( this, action_name( category ), tag );
309 const char *pkgXmlNode::ArchiveName()
311 /* Applicable only for XML nodes designated as "release".
313 * Retrieve the actual tarball name, if specified, from the
314 * "tarname" property of a contained "download" element, within
315 * an XML node designated as a "release" element.
317 * Returns a pointer to the text of the "tarname" property of the
318 * contained "download" element, or to the "tarname" property of
319 * the containing "release" element, if it does not contain an
320 * alternative specification within a "download" element; if
321 * unresolved to either of these, returns NULL.
323 return pkgArchiveName( this, download_key, 1 );
326 /* $RCSfile$: end of file */