7 * Written by Keith Marshall <keith@users.osdn.me>
8 * Copyright (C) 2009-2013, 2020, 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.
31 #if IMPLEMENTATION_LEVEL == PACKAGE_BASE_COMPONENT
37 /* Define an API for registering environment variables.
39 EXTERN_C int pkgPutEnv( int, char* );
41 #define PKG_PUTENV_DIRSEP_MSW (0x01)
42 #define PKG_PUTENV_DIRSEP_POSIX (0x02)
43 #define PKG_PUTENV_SCAN_VARNAME (0x04)
44 #define PKG_PUTENV_NAME_TOUPPER (0x08)
46 #define PKG_PUTENV_FLAGS_MASK (0x0F)
48 /* Begin class declarations.
53 class pkgProgressMeter
55 /* An abstract base class, from which the controller class
56 * for a progress meter dialogue window may be derived.
59 virtual void SetValue( int ) = 0;
60 virtual void SetRange( int, int ) = 0;
61 virtual int Annotate( const char *, ... ) = 0;
64 class pkgXmlNode : public TiXmlElement
66 /* A minimal emulation of the wxXmlNode class, founded on
67 * the tinyxml implementation of the TiXmlElement class, and
68 * subsequently extended by application specific features.
73 inline pkgXmlNode( const char* name ):TiXmlElement( name ){}
74 inline pkgXmlNode( const pkgXmlNode& src ):TiXmlElement( src ){}
78 inline const char* GetName()
80 /* Retrieve the identifying name of the XML tag;
81 * tinyxml calls this the element "value"...
85 inline pkgXmlNode* GetParent()
87 /* wxXmlNode provides this equivalant of tinyxml's
90 return (pkgXmlNode*)(Parent());
92 inline pkgXmlNode* GetChildren()
94 /* wxXmlNode provides only this one method to access
95 * the children of an element; it is equivalent to the
96 * FirstChild() method in tinyxml's arsenal.
98 return (pkgXmlNode*)(FirstChild());
100 inline pkgXmlNode* GetNext()
102 /* This is wxXmlNode's method for visiting other children
103 * of an element, after the first found by GetChildren();
104 * it is equivalent to tinyxml's NextSibling().
106 return (pkgXmlNode*)(NextSibling());
108 inline const char* GetPropVal( const char* name, const char* subst )
110 /* tinyxml has no direct equivalent for this wxXmlNode method,
111 * (which substitutes default "subst" text for an omitted property),
112 * but it may be trivially emulated, using the Attribute() method.
115 if( (retval = Attribute( name )) == NULL ) return subst;
118 inline pkgXmlNode* AddChild( TiXmlNode *child )
120 /* This is wxXmlNode's method for adding a child node, it is
121 * equivalent to tinyxml's LinkEndChild() method.
123 return (pkgXmlNode*)(LinkEndChild( child ));
125 inline bool DeleteChild( pkgXmlNode *child )
127 /* Both TiXmlNode and wxXmlNode have RemoveChild methods, but the
128 * implementations are semantically different; for tinyxml, we may
129 * simply use the RemoveChild method here, where for wxXmlNode, we
130 * would use RemoveChild followed by `delete child'.
132 return RemoveChild( child );
135 /* Additional methods specific to the application.
137 inline pkgXmlNode *GetDocumentRoot()
139 /* Convenience method to retrieve a pointer to the document root.
141 return (pkgXmlNode*)(GetDocument()->RootElement());
143 inline bool IsElementOfType( const char* tagname )
145 /* Confirm if the owner XML node represents a data element
146 * with the specified "tagname".
148 return strcmp( GetName(), tagname ) == 0;
151 /* Methods to determine which packages should be displayed
152 * in the package list pane of the GUI client.
154 inline bool IsVisibleGroupMember();
155 inline bool IsVisibleClass();
157 /* Methods for retrieving the system root management records
158 * for a specified installed subsystem.
160 pkgXmlNode *GetSysRoot( const char* );
161 pkgXmlNode *GetInstallationRecord( const char* );
163 /* Methods for mapping the package group hierarchy.
165 inline void SetPackageGroupHierarchyMapper();
166 inline void MapPackageGroupHierarchy( pkgXmlNode* );
168 /* Type definition for a helper function, which must be assigned
169 * to the package group hierarchy mapper, in order to enable it.
171 typedef void (*GroupHierarchyMapper)( pkgXmlNode*, pkgXmlNode* );
173 /* The following pair of methods provide an iterator
174 * for enumerating the contained nodes, within the owner,
175 * which themselves exhibit a specified tagname.
177 pkgXmlNode* FindFirstAssociate( const char* );
178 pkgXmlNode* FindNextAssociate( const char* );
180 /* Specific to XML node elements of type "release",
181 * the following pair of methods retrieve the actual name of
182 * the release tarball, and its associated source code tarball,
183 * as they are named on the project download servers.
185 const char* ArchiveName();
186 const char* SourceArchiveName( unsigned long );
188 /* The following retrieves an attribute which may have been
189 * specified on an ancestor (container) node; typically used to
190 * retrieve the package name or alias attributes which are to
191 * be associated with a release.
193 const char *GetContainerAttribute( const char*, const char* = NULL );
195 /* Any package may have associated scripts; the following
196 * method invokes them on demand.
198 inline int InvokeScript( const char *context )
200 /* The actual implementation is delegated to the following
201 * (private) overloaded method.
203 return InvokeScript( 0, context );
207 /* Helpers used to implement the preceding InvokeScript() method.
209 int InvokeScript( int, const char* );
210 int DispatchScript( int, const char*, const char*, pkgXmlNode* );
212 /* Hook via which the requisite helper function is attached
213 * to the package group hierarchy mapper.
215 static GroupHierarchyMapper PackageGroupHierarchyMapper;
218 enum { to_remove = 0, to_install, selection_types };
222 /* A class implementing a bi-directionally linked list of
223 * "action" descriptors, which is to be associated with the
224 * pkgXmlDocument class, specifying actions to be performed
225 * on the managed software installation.
228 /* Pointers to predecessor and successor in the linked list
229 * comprising the schedule of action items.
234 /* Flags define the specific action associated with this item.
238 /* Criteria for selection of package versions associated with
241 const char* min_wanted;
242 const char* max_wanted;
244 /* Pointers to the XML database entries for the package selected
245 * for processing by this action.
247 pkgXmlNode* selection[ selection_types ];
249 /* Methods for retrieving packages from a distribution server.
251 void DownloadArchiveFiles( pkgActionItem* );
252 void DownloadSingleArchive( const char*, const char* );
257 pkgActionItem( pkgActionItem* = NULL, pkgActionItem* = NULL );
259 /* Methods for assembling action items into a linked list.
261 pkgActionItem* Append( pkgActionItem* = NULL );
262 pkgActionItem* Insert( pkgActionItem* = NULL );
264 /* Methods for compiling the schedule of actions.
266 unsigned long SetAuthorities( pkgActionItem* );
267 inline unsigned long HasAttribute( unsigned long required )
269 return flags & required;
271 pkgActionItem* GetReference( pkgXmlNode* );
272 pkgActionItem* GetReference( pkgActionItem& );
273 pkgActionItem* Schedule( unsigned long, pkgActionItem& );
274 inline pkgActionItem* SuppressRedundantUpgrades( void );
275 inline void CancelScheduledAction( void );
276 inline void SetPrimary( pkgActionItem* );
278 /* Method to enumerate and identify pending changes,
279 * and/or check for residual unapplied changes.
281 unsigned long EnumeratePendingActions( int = 0 );
283 /* Methods for defining the selection criteria for
284 * packages to be processed.
286 void ApplyBounds( pkgXmlNode *, const char * );
287 pkgXmlNode* SelectIfMostRecentFit( pkgXmlNode* );
288 const char* SetRequirements( pkgXmlNode*, pkgSpecs* );
289 inline void SelectPackage( pkgXmlNode *pkg, int opt = to_install )
291 /* Mark a package as the selection for a specified action.
293 selection[ opt ] = pkg;
295 inline pkgXmlNode* Selection( int mode = to_install )
297 /* Retrieve the package selection for a specified action.
299 return selection[ mode ];
301 void ConfirmInstallationStatus();
303 /* Method to display the URI whence a package may be downloaded.
305 void PrintURI( const char*, int (*)( const char* ) = puts );
307 /* Methods to download and unpack one or more source archives.
309 void GetSourceArchive( pkgXmlNode*, unsigned long );
310 void GetScheduledSourceArchives( unsigned long );
312 /* Methods for processing all scheduled actions.
314 void Execute( bool = true );
315 inline void DownloadArchiveFiles( void );
317 /* Method to manipulate error trapping, control, and state
318 * flags for the schedule of actions.
320 void Assert( unsigned long, unsigned long = ~0UL, pkgActionItem* = NULL );
322 /* Method to filter actions from an action list: the default is to
323 * clear ALL entries; specify a value of ACTION_MASK for the second
324 * argument, to filter out entries with no assigned action.
326 pkgActionItem *Clear( pkgActionItem* = NULL, unsigned long = 0UL );
327 pkgActionItem *Clear( unsigned long mask ){ return Clear( this, mask ); }
334 class pkgXmlDocument : public TiXmlDocument
336 /* Minimal emulation of the wxXmlDocument class, founded on
337 * the tinyxml implementation of the TiXmlDocument class.
342 inline pkgXmlDocument(): progress_meter( NULL ){}
343 inline pkgXmlDocument( const char* name ): progress_meter( NULL )
345 /* tinyxml has a similar constructor, but unlike wxXmlDocument,
346 * it DOES NOT automatically load the document; force it.
350 /* Always begin with an empty actions list.
359 /* tinyxml doesn't have this, but instead provides a complementary
360 * `Error()' indicator, so to simulate `IsOk()'...
364 inline pkgXmlNode* GetRoot()
366 /* This is wxXmlDocument's method for locating the document root;
367 * it is equivalent to tinyxml's RootElement() method.
369 return (pkgXmlNode *)(RootElement());
371 inline void AddDeclaration
372 ( const char *version, const char *encoding, const char *standalone )
374 /* Not a standard method of either wxXmlDocumemnt or TiXmlDocument;
375 * this is a convenience method for setting up a new XML database.
377 LinkEndChild( new TiXmlDeclaration( version, encoding, standalone ) );
379 inline void SetRoot( TiXmlNode* root )
381 /* tinyxml has no direct equivalent for this wxXmlDocument method;
382 * to emulate it, we must first explicitly delete an existing root
383 * node, if any, then link the new root node as a document child.
386 if( (oldroot = GetRoot()) != NULL )
388 LinkEndChild( root );
390 inline bool Save( const char *filename )
392 /* This wxXmlDocument method for saving the database is equivalent
393 * to the corresponding tinyxml SaveFile( const char* ) method.
395 return SaveFile( filename );
399 /* Properties specifying the schedule of actions.
401 unsigned long request;
402 pkgActionItem* actions;
405 /* Method to interpret user preferences for mingw-get processing
406 * options, which are specified within profile.xml rather than on
409 void EstablishPreferences( const char* = NULL );
411 /* Method to synchronise the state of the local package manifest
412 * with the master copy held on the distribution server.
414 void SyncRepository( const char*, pkgXmlNode* );
416 /* Method to merge content from repository-specific package lists
417 * into the central XML package database.
419 pkgXmlNode* BindRepositories( bool );
421 /* Method to load the system map, and the lists of installed
422 * packages associated with each specified sysroot.
424 void LoadSystemMap();
426 /* Complementary method, to update the saved sysroot data associated
427 * with the active system map.
429 void UpdateSystemMap();
431 /* Method to locate the XML database entry for a named package.
433 pkgXmlNode* FindPackageByName( const char*, const char* = NULL );
435 /* Methods to retrieve and display information about packages.
437 pkgDirectory *CatalogueAllPackages();
438 void DisplayPackageInfo( int, char** );
440 /* Method to resolve the dependencies of a specified package,
441 * by walking the chain of references specified by "requires"
442 * elements in the respective package database entries.
444 void ResolveDependencies( pkgXmlNode*, pkgActionItem* = NULL );
446 /* Methods for compiling a schedule of actions.
448 pkgActionItem* Schedule( unsigned long = 0UL, const char* = NULL );
449 pkgActionItem* Schedule( unsigned long, pkgActionItem&, pkgActionItem* = NULL );
450 void RescheduleInstalledPackages( unsigned long );
452 /* Method to execute a sequence of scheduled actions.
454 inline void ExecuteActions(){ if( actions ) actions->Execute(); }
456 /* Method to clear the list of scheduled actions.
458 inline pkgActionItem* ClearScheduledActions( unsigned long mask = 0UL )
460 return actions = actions->Clear( mask );
463 /* Methods to retrieve and optionally extract source archives
464 * for a collection of dependent packages.
466 void GetSourceArchive( const char*, unsigned long );
467 inline void GetScheduledSourceArchives( unsigned long category )
469 actions->GetScheduledSourceArchives( category );
472 /* Facility for monitoring of XML document processing operations.
475 pkgProgressMeter* progress_meter;
478 inline pkgProgressMeter *ProgressMeter( void )
480 return progress_meter;
482 inline pkgProgressMeter *AttachProgressMeter( pkgProgressMeter *attachment )
484 if( progress_meter == NULL )
485 progress_meter = attachment;
486 return progress_meter;
488 inline void DetachProgressMeter( pkgProgressMeter *attachment )
490 if( attachment == progress_meter )
491 progress_meter = NULL;
495 EXTERN_C const char *xmlfile( const char*, const char* = NULL );
496 EXTERN_C int has_keyword( const char*, const char* );
498 #undef USES_SAFE_STRCMP
499 #define USES_SAFE_STRCMP 1
501 #endif /* PACKAGE_BASE_COMPONENT */
503 #if USES_SAFE_STRCMP && ! HAVE_SAFE_STRCMP
505 typedef int (*strcmp_function)( const char *, const char * );
508 bool safe_strcmp( strcmp_function strcmp, const char *value, const char *proto )
510 /* Helper to compare a pair of "C" strings for equality,
511 * accepting NULL as a match for anything; for non-NULL matches,
512 * case sensitivity is determined by choice of strcmp function.
514 * N.B. Unlike the 'strcmp' function which this calls, this is
515 * a boolean function, returning TRUE when the 'strcmp' result
516 * is zero, (i.e. the sense of the result is inverted).
518 return (value == NULL) || (proto == NULL) || (strcmp( value, proto ) == 0);
521 /* Define a safe_strcmp() alias for an explicitly case sensitive match.
523 #define match_if_explicit( A, B ) safe_strcmp( strcmp, (A), (B) )
525 /* Further safe_strcmp() aliases provide for matching subsystem names,
526 * with implementation dependent case sensitivity...
529 /* The MS-Windows file system is intrinsically case insensitive,
530 * so we prefer to match both subsystem and file names in a case
531 * insensitive manner...
533 # ifndef CASE_INSENSITIVE_SUBSYSTEMS
534 # define CASE_INSENSITIVE_SUBSYSTEMS 1
536 # ifndef CASE_INSENSITIVE_FILESYSTEM
537 # define CASE_INSENSITIVE_FILESYSTEM 1
540 /* The preferred name for MS-Windows' case insensitive string
541 * matching function, equivalent to POSIX strcasecmp(); MinGW's
542 * string.h will have established this mapping already, so we
543 * don't introduce a (possibly incompatible) redefinition.
545 # define strcasecmp _stricmp
548 /* On other systems, we prefer to adopt case sensitive matching
549 * strategies for subsystem and file names.
551 # ifndef CASE_INSENSITIVE_SUBSYSTEMS
552 # define CASE_INSENSITIVE_SUBSYSTEMS 0
554 # ifndef CASE_INSENSITIVE_FILESYSTEM
555 # define CASE_INSENSITIVE_FILESYSTEM 0
559 #if CASE_INSENSITIVE_SUBSYSTEMS
560 # define subsystem_strcmp( A, B ) safe_strcmp( strcasecmp, (A), (B) )
562 # define subsystem_strcmp( A, B ) safe_strcmp( strcmp, (A), (B) )
565 /* ...and similarly, for matching of file names.
567 #if CASE_INSENSITIVE_FILESYSTEM
568 # define pkg_strcmp( A, B ) safe_strcmp( strcasecmp, (A), (B) )
570 # define pkg_strcmp( A, B ) safe_strcmp( strcmp, (A), (B) )
573 #undef HAVE_SAFE_STRCMP
574 #define HAVE_SAFE_STRCMP 1
578 #endif /* PKGBASE_H: $RCSfile$: end of file */