7 * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
8 * Copyright (C) 2009, 2010, 2011, 2012, MinGW.org Project
11 * Public interface for the package directory management routines;
12 * declares the XML data structures, and their associated class APIs,
13 * which are used to describe packages and their interdependencies.
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.
37 # define EXTERN_C extern "C"
43 /* Adopt sensible defaults for matching subsystem and file names...
47 * The MS-Windows file system is intrinsically case insensitive,
48 * so we prefer to match both subsystem and file names in a case
49 * insensitive manner...
51 # ifndef CASE_INSENSITIVE_SUBSYSTEMS
52 # define CASE_INSENSITIVE_SUBSYSTEMS 1
54 # ifndef CASE_INSENSITIVE_FILESYSTEM
55 # define CASE_INSENSITIVE_FILESYSTEM 1
58 * The preferred name for MS-Windows' case insensitive string
59 * matching function, equivalent to POSIX strcasecmp().
61 # define strcasecmp stricmp
63 /* On other systems, we prefer to adopt case sensitive matching
64 * strategies for subsystem and file names.
66 # ifndef CASE_INSENSITIVE_SUBSYSTEMS
67 # define CASE_INSENSITIVE_SUBSYSTEMS 0
69 # ifndef CASE_INSENSITIVE_FILESYSTEM
70 # define CASE_INSENSITIVE_FILESYSTEM 0
74 /* Define an API for registering environment variables.
76 EXTERN_C int pkgPutEnv( int, char* );
78 #define PKG_PUTENV_DIRSEP_MSW (0x01)
79 #define PKG_PUTENV_DIRSEP_POSIX (0x02)
80 #define PKG_PUTENV_SCAN_VARNAME (0x04)
81 #define PKG_PUTENV_NAME_TOUPPER (0x08)
83 #define PKG_PUTENV_FLAGS_MASK (0x0F)
85 /* Begin class declarations.
94 class pkgProgressMeter
96 /* An abstract base class, from which the controller class
97 * for a progress meter dialogue window may be derived.
100 virtual void SetValue( int ) = 0;
101 virtual void SetRange( int, int ) = 0;
102 virtual int Annotate( const char *, ... ) = 0;
105 AppWindowMaker *referrer;
106 pkgProgressMeter( AppWindowMaker *ref = NULL ): referrer( ref ){}
110 class pkgXmlNode : public TiXmlElement
112 /* A minimal emulation of the wxXmlNode class, founded on
113 * the tinyxml implementation of the TiXmlElement class, and
114 * subsequently extended by application specific features.
119 inline pkgXmlNode( const char* name ):TiXmlElement( name ){}
120 inline pkgXmlNode( const pkgXmlNode& src ):TiXmlElement( src ){}
124 * Note that tinyxml is generally careless about checking for
125 * possible dereferencing of NULL pointers; thus, many of these
126 * wrappers include appropriate checks, to prevent this.
128 inline const char* GetName()
130 /* Retrieve the identifying name of the XML tag;
131 * tinyxml calls this the element "value"...
133 return this ? Value() : NULL;
135 inline pkgXmlNode* GetParent()
137 /* wxXmlNode provides this equivalant of tinyxml's
140 return this ? (pkgXmlNode*)(Parent()) : NULL;
142 inline pkgXmlNode* GetChildren()
144 /* wxXmlNode provides only this one method to access
145 * the children of an element; it is equivalent to the
146 * FirstChild() method in tinyxml's arsenal.
148 return this ? (pkgXmlNode*)(FirstChild()) : NULL;
150 inline pkgXmlNode* GetNext()
152 /* This is wxXmlNode's method for visiting other children
153 * of an element, after the first found by GetChildren();
154 * it is equivalent to tinyxml's NextSibling().
156 return this ? (pkgXmlNode*)(NextSibling()) : NULL;
158 inline const char* GetPropVal( const char* name, const char* subst )
160 /* tinyxml has no direct equivalent for this wxXmlNode method,
161 * (which substitutes default "subst" text for an omitted property),
162 * but it may be trivially emulated, using the Attribute() method.
164 const char* retval = this ? Attribute( name ) : subst;
165 return retval ? retval : subst;
167 inline pkgXmlNode* AddChild( TiXmlNode *child )
169 /* This is wxXmlNode's method for adding a child node, it is
170 * equivalent to tinyxml's LinkEndChild() method.
172 return this ? (pkgXmlNode*)(LinkEndChild( child )) : NULL;
174 inline bool DeleteChild( pkgXmlNode *child )
176 /* Both TiXmlNode and wxXmlNode have RemoveChild methods, but the
177 * implementations are semantically different; for tinyxml, we may
178 * simply use the RemoveChild method here, where for wxXmlNode, we
179 * would use RemoveChild followed by `delete child'.
181 return this ? RemoveChild( child ) : false;
184 /* Additional methods specific to the application.
186 inline pkgXmlNode *GetDocumentRoot()
188 /* Convenience method to retrieve a pointer to the document root.
190 return this ? (pkgXmlNode*)(GetDocument()->RootElement()) : NULL;
192 inline bool IsElementOfType( const char* tagname )
194 /* Confirm if the owner XML node represents a data element
195 * with the specified "tagname".
197 return this ? strcmp( GetName(), tagname ) == 0 : false;
200 /* Methods for retrieving the system root management records
201 * for a specified installed subsystem.
203 pkgXmlNode *GetSysRoot( const char* );
204 pkgXmlNode *GetInstallationRecord( const char* );
206 /* The following pair of methods provide an iterator
207 * for enumerating the contained nodes, within the owner,
208 * which themselves exhibit a specified tagname.
210 pkgXmlNode* FindFirstAssociate( const char* );
211 pkgXmlNode* FindNextAssociate( const char* );
213 /* Specific to XML node elements of type "release",
214 * the following pair of methods retrieve the actual name of
215 * the release tarball, and its associated source code tarball,
216 * as they are named on the project download servers.
218 const char* ArchiveName();
219 const char* SourceArchiveName( unsigned long );
221 /* The following retrieves an attribute which may have been
222 * specified on an ancestor (container) node; typically used to
223 * retrieve the package name or alias attributes which are to
224 * be associated with a release.
226 const char *GetContainerAttribute( const char*, const char* = NULL );
228 /* Any package may have associated scripts; the following
229 * method invokes them on demand.
231 inline int InvokeScript( const char *context )
233 /* The actual implementation is delegated to the following
234 * (private) overloaded method.
236 return InvokeScript( 0, context );
240 /* Helpers used to implement the preceding InvokeScript() method.
242 int InvokeScript( int, const char* );
243 int DispatchScript( int, const char*, const char*, pkgXmlNode* );
246 enum { to_remove = 0, to_install, selection_types };
250 /* A class implementing a bi-directionally linked list of
251 * "action" descriptors, which is to be associated with the
252 * pkgXmlDocument class, specifying actions to be performed
253 * on the managed software installation.
256 /* Pointers to predecessor and successor in the linked list
257 * comprising the schedule of action items.
262 /* Flags define the specific action associated with this item.
266 /* Criteria for selection of package versions associated with
269 const char* min_wanted;
270 const char* max_wanted;
272 /* Pointers to the XML database entries for the package selected
273 * for processing by this action.
275 pkgXmlNode* selection[ selection_types ];
277 /* Methods for retrieving packages from a distribution server.
279 void DownloadArchiveFiles( pkgActionItem* );
280 void DownloadSingleArchive( const char*, const char* );
285 pkgActionItem( pkgActionItem* = NULL, pkgActionItem* = NULL );
287 /* Methods for assembling action items into a linked list.
289 pkgActionItem* Append( pkgActionItem* = NULL );
290 pkgActionItem* Insert( pkgActionItem* = NULL );
292 /* Methods for compiling the schedule of actions.
294 unsigned long SetAuthorities( pkgActionItem* );
295 inline unsigned long HasAttribute( unsigned long required )
297 return (this != NULL) ? flags & required : 0UL;
299 pkgActionItem* GetReference( pkgXmlNode* );
300 pkgActionItem* GetReference( pkgActionItem& );
301 pkgActionItem* Schedule( unsigned long, pkgActionItem& );
302 inline unsigned long CancelScheduledAction( void );
303 inline void SetPrimary( pkgActionItem* );
305 /* Method to enumerate and identify pending changes,
306 * and/or check for residual unapplied changes.
308 unsigned long EnumeratePendingActions( int = 0 );
310 /* Methods for defining the selection criteria for
311 * packages to be processed.
313 void ApplyBounds( pkgXmlNode *, const char * );
314 pkgXmlNode* SelectIfMostRecentFit( pkgXmlNode* );
315 const char* SetRequirements( pkgXmlNode*, pkgSpecs* );
316 inline void SelectPackage( pkgXmlNode *pkg, int opt = to_install )
318 /* Mark a package as the selection for a specified action.
320 if (this != NULL) selection[ opt ] = pkg;
322 inline pkgXmlNode* Selection( int mode = to_install )
324 /* Retrieve the package selection for a specified action.
326 return (this != NULL) ? selection[ mode ] : NULL;
328 void ConfirmInstallationStatus();
330 /* Method to display the URI whence a package may be downloaded.
332 void PrintURI( const char*, int (*)( const char* ) = puts );
334 /* Methods to download and unpack one or more source archives.
336 void GetSourceArchive( pkgXmlNode*, unsigned long );
337 void GetScheduledSourceArchives( unsigned long );
339 /* Methods for processing all scheduled actions.
341 void Execute( bool = true );
342 inline void DownloadArchiveFiles( void );
344 /* Method to manipulate error trapping, control, and state
345 * flags for the schedule of actions.
347 void Assert( unsigned long, unsigned long = ~0UL, pkgActionItem* = NULL );
349 /* Method to filter actions from an action list: the default is to
350 * clear ALL entries; specify a value of ACTION_MASK for the second
351 * argument, to filter out entries with no assigned action.
353 pkgActionItem *Clear( pkgActionItem* = NULL, unsigned long = 0UL );
354 pkgActionItem *Clear( unsigned long mask ){ return Clear( this, mask ); }
361 class pkgXmlDocument : public TiXmlDocument
363 /* Minimal emulation of the wxXmlDocument class, founded on
364 * the tinyxml implementation of the TiXmlDocument class.
369 inline pkgXmlDocument(): progress_meter( NULL ){}
370 inline pkgXmlDocument( const char* name ): progress_meter( NULL )
372 /* tinyxml has a similar constructor, but unlike wxXmlDocument,
373 * it DOES NOT automatically load the document; force it.
377 /* Always begin with an empty actions list.
386 /* tinyxml doesn't have this, but instead provides a complementary
387 * `Error()' indicator, so to simulate `IsOk()'...
391 inline pkgXmlNode* GetRoot()
393 /* This is wxXmlDocument's method for locating the document root;
394 * it is equivalent to tinyxml's RootElement() method.
396 return (pkgXmlNode *)(RootElement());
398 inline void AddDeclaration
399 ( const char *version, const char *encoding, const char *standalone )
401 /* Not a standard method of either wxXmlDocumemnt or TiXmlDocument;
402 * this is a convenience method for setting up a new XML database.
404 LinkEndChild( new TiXmlDeclaration( version, encoding, standalone ) );
406 inline void SetRoot( TiXmlNode* root )
408 /* tinyxml has no direct equivalent for this wxXmlDocument method;
409 * to emulate it, we must first explicitly delete an existing root
410 * node, if any, then link the new root node as a document child.
413 if( (oldroot = GetRoot()) != NULL )
415 LinkEndChild( root );
417 inline bool Save( const char *filename )
419 /* This wxXmlDocument method for saving the database is equivalent
420 * to the corresponding tinyxml SaveFile( const char* ) method.
422 return SaveFile( filename );
426 /* Properties specifying the schedule of actions.
428 unsigned long request;
429 pkgActionItem* actions;
432 /* Method to interpret user preferences for mingw-get processing
433 * options, which are specified within profile.xml rather than on
436 void EstablishPreferences();
438 /* Method to synchronise the state of the local package manifest
439 * with the master copy held on the distribution server.
441 void SyncRepository( const char*, pkgXmlNode* );
443 /* Method to merge content from repository-specific package lists
444 * into the central XML package database.
446 pkgXmlNode* BindRepositories( bool );
448 /* Method to load the system map, and the lists of installed
449 * packages associated with each specified sysroot.
451 void LoadSystemMap();
453 /* Complementary method, to update the saved sysroot data associated
454 * with the active system map.
456 void UpdateSystemMap();
458 /* Method to locate the XML database entry for a named package.
460 pkgXmlNode* FindPackageByName( const char*, const char* = NULL );
462 /* Methods to retrieve and display information about packages.
464 pkgDirectory *CatalogueAllPackages();
465 void DisplayPackageInfo( int, char** );
467 /* Method to resolve the dependencies of a specified package,
468 * by walking the chain of references specified by "requires"
469 * elements in the respective package database entries.
471 void ResolveDependencies( pkgXmlNode*, pkgActionItem* = NULL );
473 /* Methods for compiling a schedule of actions.
475 pkgActionItem* Schedule( unsigned long = 0UL, const char* = NULL );
476 pkgActionItem* Schedule( unsigned long, pkgActionItem&, pkgActionItem* = NULL );
477 void RescheduleInstalledPackages( unsigned long );
479 /* Method to execute a sequence of scheduled actions.
481 inline void ExecuteActions(){ actions->Execute(); }
483 /* Method to clear the list of scheduled actions.
485 inline pkgActionItem* ClearScheduledActions( unsigned long mask = 0UL )
487 return actions = actions->Clear( mask );
490 /* Methods to retrieve and optionally extract source archives
491 * for a collection of dependent packages.
493 void GetSourceArchive( const char*, unsigned long );
494 inline void GetScheduledSourceArchives( unsigned long category )
496 actions->GetScheduledSourceArchives( category );
499 /* Facility for monitoring of XML document processing operations.
502 pkgProgressMeter* progress_meter;
505 inline pkgProgressMeter *ProgressMeter( void )
507 return progress_meter;
509 inline pkgProgressMeter *AttachProgressMeter( pkgProgressMeter *attachment )
511 if( progress_meter == NULL )
512 progress_meter = attachment;
513 return progress_meter;
515 inline void DetachProgressMeter( pkgProgressMeter *attachment )
517 if( attachment == progress_meter )
518 progress_meter = NULL;
522 EXTERN_C const char *xmlfile( const char*, const char* = NULL );
523 EXTERN_C int has_keyword( const char*, const char* );
525 typedef int (*strcmp_function)( const char *, const char * );
528 bool safe_strcmp( strcmp_function strcmp, const char *value, const char *proto )
530 /* Helper to compare a pair of "C" strings for equality,
531 * accepting NULL as a match for anything; for non-NULL matches,
532 * case sensitivity is determined by choice of strcmp function.
534 * N.B. Unlike the 'strcmp' function which this calls, this is
535 * a boolean function, returning TRUE when the 'strcmp' result
536 * is zero, (i.e. the sense of the result is inverted).
538 return (value == NULL) || (proto == NULL) || (strcmp( value, proto ) == 0);
541 /* Define a safe_strcmp() alias for an explicitly case sensitive match.
543 #define match_if_explicit( A, B ) safe_strcmp( strcmp, (A), (B) )
545 /* Further safe_strcmp() aliases provide for matching subsystem names,
546 * with implementation dependent case sensitivity...
548 #if CASE_INSENSITIVE_SUBSYSTEMS
549 # define subsystem_strcmp( A, B ) safe_strcmp( strcasecmp, (A), (B) )
551 # define subsystem_strcmp( A, B ) safe_strcmp( strcmp, (A), (B) )
554 /* ...and similarly, for matching of file names.
556 #if CASE_INSENSITIVE_FILESYSTEM
557 # define pkg_strcmp( A, B ) safe_strcmp( strcasecmp, (A), (B) )
559 # define pkg_strcmp( A, B ) safe_strcmp( strcmp, (A), (B) )
562 #endif /* PKGBASE_H: $RCSfile$: end of file */