6 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
7 * Copyright (C) 2009, 2010, 2011, MinGW Project
10 * Implementation of repository binding for the pkgXmlDocument class.
13 * This is free software. Permission is granted to copy, modify and
14 * redistribute this software, under the provisions of the GNU General
15 * Public License, Version 3, (or, at your option, any later version),
16 * as published by the Free Software Foundation; see the file COPYING
17 * for licensing details.
19 * Note, in particular, that this software is provided "as is", in the
20 * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not
21 * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY
22 * PARTICULAR PURPOSE. Under no circumstances will the author, or the
23 * MinGW Project, accept liability for any damages, however caused,
24 * arising from the use of this software.
39 /* A locally defined class to facilitate recursive retrieval
40 * of package lists, from any specified repository.
43 pkgRepository( pkgXmlDocument*, pkgXmlNode*, pkgXmlNode*, bool );
46 void GetPackageList( const char* );
47 void GetPackageList( pkgXmlNode* );
51 pkgXmlNode *repository;
52 pkgXmlDocument *owner;
56 pkgRepository::pkgRepository
60 ( pkgXmlDocument *client, pkgXmlNode *db, pkgXmlNode *ref, bool mode ):
61 owner( client ), dbase( db ), repository( ref ), force_update( mode ){}
63 void pkgRepository::GetPackageList( const char *dname )
65 /* Helper to retrieve and recursively process a named package list.
67 * FIXME: having made this recursively process multiple catalogues,
68 * potentially from multiple independent repositories, we may have
69 * introduced potential for catalogue name clashes; we need to add
70 * name hashing in the local catalogue cache, to avoid conflicts.
75 if( (dfile = xmlfile( dname )) != NULL )
77 /* Check for a locally cached copy of the "package-list" file...
79 if( force_update || (access( dfile, F_OK ) != 0) )
81 /* When performing an "update", or if no local copy is available...
82 * Force a "sync", to fetch a copy from the public host.
84 dmh_printf( "Update catalogue: %s.xml\n", dname );
85 owner->SyncRepository( dname, repository );
88 /* We SHOULD now have a locally cached copy of the package-list;
89 * attempt to merge it into the active profile database...
91 pkgXmlDocument merge( dfile );
94 /* We successfully loaded the XML catalogue; refer to its
97 if( pkgOptions()->Test( OPTION_VERBOSE ) > 1 )
98 dmh_printf( "Load catalogue: %s.xml\n", dname );
99 pkgXmlNode *catalogue, *pkglist;
100 if( (catalogue = merge.GetRoot()) != NULL )
102 /* ...read it, selecting each of the "package-collection"
103 * records contained within it...
105 pkglist = catalogue->FindFirstAssociate( package_collection_key );
106 while( pkglist != NULL )
108 /* ...and append a copy of each to the active profile...
110 dbase->LinkEndChild( pkglist->Clone() );
112 /* Move on to the next "package-collection" (if any)
113 * within the current catalogue...
115 pkglist = pkglist->FindNextAssociate( package_collection_key );
118 /* Recursively incorporate any additional package lists,
119 * which may be specified within the current catalogue...
121 GetPackageList( catalogue->FindFirstAssociate( package_list_key ) );
125 { /* The specified catalogue could not be successfully loaded;
126 * emit a warning diagnostic message, and otherwise ignore it.
128 dmh_notify( DMH_WARNING, "Load catalogue: FAILED: %s.xml\n", dname );
131 /* However we handled it, the XML file's path name in "dfile" was
132 * allocated on the heap; we lose its reference on termination of
133 * this loop, so we must free it to avoid a memory leak.
135 free( (void *)(dfile) );
140 void pkgRepository::GetPackageList( pkgXmlNode *catalogue )
142 /* Helper method to retrieve a set of package list specifications
143 * from a "package-list" catalogue; after processing the specified
144 * "catalogue" it iterates over any sibling XML elements which are
145 * also designated as being of the "package-list" type.
147 * Note: we assume that the passed catalogue element actually
148 * DOES represent a "package-list" element; we do not check this,
149 * because the class declaration is not exposed externally to this
150 * translation unit, and we only ever call this from within the
151 * unit, when we have a "package-list" element to process.
153 while( catalogue != NULL )
155 /* Evaluate each identified "package-list" catalogue in turn...
157 GetPackageList( catalogue->GetPropVal( catalogue_key, NULL ) );
159 /* A repository may comprise an arbitrary collection of software
160 * catalogues; move on, to process the next catalogue (if any) in
161 * the current repository collection.
163 catalogue = catalogue->FindNextAssociate( package_list_key );
167 pkgXmlNode *pkgXmlDocument::BindRepositories( bool force_update )
169 /* Identify the repositories specified in the application profile,
170 * and merge their associated package distribution lists into the
171 * active XML database, which is bound to the profile.
173 pkgXmlNode *dbase = GetRoot();
175 /* Before blindly proceeding, perform a sanity check...
176 * Verify that this XML database defines an application profile,
177 * and that the associated application is "mingw-get"...
179 if( (strcmp( dbase->GetName(), profile_key ) == 0)
180 && (strcmp( dbase->GetPropVal( application_key, "?" ), "mingw-get") == 0) )
182 /* Sanity check passed...
183 * Walk the XML data tree, selecting "repository" specifications...
185 pkgXmlNode *repository = dbase->FindFirstAssociate( repository_key );
186 while( repository != NULL )
188 /* For each "repository" specified, identify its "catalogues"...
190 pkgRepository client( this, dbase, repository, force_update );
191 pkgXmlNode *catalogue = repository->FindFirstAssociate( package_list_key );
192 if( catalogue == NULL )
194 * This repository specification doesn't identify any named
195 * package list, so try the default, (which is named to match
196 * the XML key name for the "package-list" element)...
198 client.GetPackageList( package_list_key );
201 /* At least one package list catalogue is specified; load it,
202 * and any others which are explicitly identified...
204 client.GetPackageList( catalogue );
206 /* Similarly, a complete distribution may draw from an arbitrary set
207 * of distinct repositories; move on, to process the next repository
208 * specified (if any).
210 repository = repository->FindNextAssociate( repository_key );
213 /* On successful completion, return a pointer to the root node
214 * of the active XML profile.
219 /* Fall through on total failure to interpret the profile, returning
220 * NULL to indicate failure.
225 /* $RCSfile$: end of file */