OSDN Git Service

Implement package installer for tar archives.
[mingw/mingw-get.git] / src / pkgbase.h
1 #ifndef PKGBASE_H
2 /*
3  * pkgbase.h
4  *
5  * $Id$
6  *
7  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
8  * Copyright (C) 2009, 2010, MinGW Project
9  *
10  *
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.
14  *
15  *
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.
21  *
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.
28  *
29  */
30 #define PKGBASE_H  1
31
32 #include <tinyxml.h>
33 #include <tinystr.h>
34
35 #ifndef EXTERN_C
36 # ifdef __cplusplus
37 #  define EXTERN_C extern "C"
38 # else
39 #  define EXTERN_C
40 # endif
41 #endif
42
43 class pkgXmlNode : public TiXmlElement
44 {
45   /* A minimal emulation of the wxXmlNode class, founded on
46    * the tinyxml implementation of the TiXmlElement class, and
47    * subsequently extended by application specific features.
48    */
49   public:
50     /* Constructors...
51      */
52     inline pkgXmlNode( const char* name ):TiXmlElement( name ){}
53     inline pkgXmlNode( const pkgXmlNode& src ):TiXmlElement( src ){}
54
55     /* Accessors...
56      */
57     inline const char* GetName()
58     {
59       /* Retrieve the identifying name of the XML tag;
60        * tinyxml calls this the element "value"...
61        */
62       return Value();
63     }
64     inline pkgXmlNode* GetParent()
65     {
66       /* wxXmlNode provides this equivalant of tinyxml's
67        * Parent() method.
68        */
69       return (pkgXmlNode*)(Parent());
70     }
71     inline pkgXmlNode* GetChildren()
72     {
73       /* wxXmlNode provides only this one method to access
74        * the children of an element; it is equivalent to the
75        * FirstChild() method in tinyxml's arsenal.
76        */
77       return (pkgXmlNode*)(FirstChild());
78     }
79     inline pkgXmlNode* GetNext()
80     {
81       /* This is wxXmlNode's method for visiting other children
82        * of an element, after the first found by GetChildren();
83        * it is equivalent to tinyxml's NextSibling().
84        */
85       return (pkgXmlNode*)(NextSibling());
86     }
87     inline const char* GetPropVal( const char* name, const char* subst )
88     {
89       /* tinyxml has no direct equivalent for this wxXmlNode method,
90        * (which substitutes default "subst" text for an omitted property),
91        * but it may be trivially emulated, using the Attribute() method.
92        */
93       const char* retval = Attribute( name );
94       return retval ? retval : subst;
95     }
96     inline pkgXmlNode* AddChild( TiXmlNode *child )
97     {
98       /* This is wxXmlNode's method for adding a child node, it is
99        * equivalent to tinyxml's LinkEndChild() method.
100        */
101       return (pkgXmlNode*)(LinkEndChild( child ));
102     }
103     inline bool DeleteChild( pkgXmlNode *child )
104     {
105       /* Both TiXmlNode and wxXmlNode have RemoveChild methods, but the
106        * implementations are semantically different; for tinyxml, we may
107        * simply use the RemoveChild method here, where for wxXmlNode, we
108        * would use RemoveChild followed by `delete child'.
109        */
110       return RemoveChild( child );
111     }
112
113     /* Additional methods specific to the application.
114      */
115     inline pkgXmlNode *GetDocumentRoot()
116     {
117       /* Convenience method to retrieve a pointer to the document root.
118        */
119       return (pkgXmlNode*)(GetDocument()->RootElement());
120     }
121     inline bool IsElementOfType( const char* tagname )
122     {
123       /* Confirm if the owner XML node represents a data element
124        * with the specified "tagname".
125        */
126       return strcmp( GetName(), tagname ) == 0;
127     }
128
129     /* Methods for retrieving the system root management records
130      * for a specified installed subsystem.
131      */
132     pkgXmlNode *GetSysRoot( const char *subsystem );
133     pkgXmlNode *GetInstallationRecord( const char* );
134
135     /* The following pair of methods provide an iterator
136      * for enumerating the contained nodes, within the owner,
137      * which themselves exhibit a specified tagname.
138      */
139     pkgXmlNode* FindFirstAssociate( const char* tagname );
140     pkgXmlNode* FindNextAssociate( const char* tagname );
141
142     /* Specific to XML node elements of type "release",
143      * the following pair of methods retrieve the actual name of
144      * the release tarball, and its associated source code tarball,
145      * as they are named on the project download servers.
146      */
147     const char* ArchiveName();
148     const char* SourceArchiveName();
149 };
150
151 enum { to_remove = 0, to_install, selection_types };
152 class pkgActionItem
153 {
154   /* A class implementing a bi-directionally linked list of
155    * "action" descriptors, which is to be associated with the
156    * pkgXmlDocument class, specifying actions to be performed
157    * on the managed software installation.
158    */
159   private:
160     /* Pointers to predecessor and successor in the linked list
161      * comprising the schedule of action items.
162      */
163     pkgActionItem* prev;
164     pkgActionItem* next;
165
166     /* Flags define the specific action associated with this item.
167      */
168     unsigned long flags;
169
170     /* Criteria for selection of package versions associated with
171      * this action item.
172      */
173     const char* min_wanted;
174     const char* max_wanted;
175
176     /* Pointers to the XML database entries for the package selected
177      * for processing by this action.
178      */
179     pkgXmlNode* selection[ selection_types ];
180
181     /* Method for retrieving packages from a distribution server.
182      */
183     void DownloadArchiveFiles( pkgActionItem* );
184
185   public:
186     /* Constructor...
187      */
188     pkgActionItem( pkgActionItem* = NULL, pkgActionItem* = NULL );
189
190     /* Methods for assembling action items into a linked list.
191      */
192     pkgActionItem* Append( pkgActionItem* = NULL );
193     pkgActionItem* Insert( pkgActionItem* = NULL );
194
195     /* Methods for compiling the schedule of actions.
196      */
197     pkgActionItem* GetReference( pkgActionItem& );
198     pkgActionItem* Schedule( unsigned long, pkgActionItem& );
199
200     /* Methods for defining the selection criteria for
201      * packages to be processed.
202      */
203     const char* SetRequirements( pkgXmlNode* );
204     pkgXmlNode* SelectIfMostRecentFit( pkgXmlNode* );
205     inline void SelectPackage( pkgXmlNode *pkg, int opt = to_install )
206     {
207       /* Mark a package as the selection for a specified action.
208        */
209       selection[ opt ] = pkg;
210     }
211     inline pkgXmlNode* Selection( int mode = to_install )
212     {
213       /* Retrieve the package selection for a specified action.
214        */
215       return selection[ mode ];
216     }
217
218     /* Method for processing all scheduled actions.
219      */
220     void Execute();
221 };
222
223 class pkgXmlDocument : public TiXmlDocument
224 {
225   /* Minimal emulation of the wxXmlDocument class, founded on
226    * the tinyxml implementation of the TiXmlDocument class.
227    */
228   public:
229     /* Constructors...
230      */
231     inline pkgXmlDocument(){}
232     inline pkgXmlDocument( const char* name )
233     {
234       /* tinyxml has a similar constructor, but unlike wxXmlDocument,
235        * it DOES NOT automatically load the document; force it.
236        */
237       LoadFile( name );
238
239       /* Always begin with an empty actions list.
240        */
241       actions = NULL;
242     }
243
244     /* Accessors...
245      */
246     inline bool IsOk()
247     {
248       /* tinyxml doesn't have this, but instead provides a complementary
249        * `Error()' indicator, so to simulate `IsOk()'...
250        */
251       return ! Error();
252     }
253     inline pkgXmlNode* GetRoot()
254     {
255       /* This is wxXmlDocument's method for locating the document root;
256        * it is equivalent to tinyxml's RootElement() method.
257        */
258       return (pkgXmlNode *)(RootElement());
259     }
260     inline void AddDeclaration
261     ( const char *version, const char *encoding, const char *standalone )
262     {
263       /* Not a standard method of either wxXmlDocumemnt or TiXmlDocument;
264        * this is a convenience method for setting up a new XML database.
265        */
266       LinkEndChild( new TiXmlDeclaration( version, encoding, standalone ) );
267     }
268     inline void SetRoot( TiXmlNode* root )
269     {
270       /* tinyxml has no direct equivalent for this wxXmlDocument method;
271        * to emulate it, we must first explicitly delete an existing root
272        * node, if any, then link the new root node as a document child.
273        */
274       pkgXmlNode *oldroot;
275       if( (oldroot = GetRoot()) != NULL )
276         delete oldroot;
277       LinkEndChild( root );
278     }
279     inline bool Save( const char *filename )
280     {
281       /* This wxXmlDocument method for saving the database is equivalent
282        * to the corresponding tinyxml SaveFile( const char* ) method.
283        */
284       return SaveFile( filename );
285     }
286
287   private:
288     /* Properties specifying the schedule of actions.
289      */
290     unsigned long request;
291     pkgActionItem* actions;
292
293     /* Method to synchronise the state of the local package manifest
294      * with the master copy held on the distribution server.
295      */
296     void SyncRepository( const char*, pkgXmlNode* );
297
298   public:
299     /* Method to merge content from repository-specific package lists
300      * into the central XML package database.
301      */
302     pkgXmlNode* BindRepositories( bool );
303
304     /* Method to load the system map, and the lists of installed
305      * packages associated with each specified sysroot.
306      */
307     void LoadSystemMap();
308
309     /* Complementary method, to update the saved sysroot data associated
310      * with the active system map.
311      */
312     void UpdateSystemMap();
313
314     /* Method to locate the XML database entry for a named package.
315      */
316     pkgXmlNode* FindPackageByName( const char*, const char* = NULL );
317
318     /* Method to resolve the dependencies of a specified package,
319      * by walking the chain of references specified by "requires"
320      * elements in the respective package database entries.
321      */
322     void ResolveDependencies( pkgXmlNode*, pkgActionItem* = NULL );
323
324     /* Methods for compiling a schedule of actions.
325      */
326     void Schedule( unsigned long, const char* );
327     pkgActionItem* Schedule( unsigned long, pkgActionItem&, pkgActionItem* = NULL );
328
329     /* Method to execute a sequence of scheduled actions.
330      */
331     inline void ExecuteActions(){ actions->Execute(); }
332 };
333
334 EXTERN_C const char *xmlfile( const char*, const char* = NULL );
335 EXTERN_C int has_keyword( const char*, const char* );
336
337 static inline
338 bool match_if_explicit( const char *value, const char *proto )
339 {
340   /* Helper to compare a pair of "C" strings for equality,
341    * accepting NULL as a match for anything.
342    */
343   return (value == NULL) || (proto == NULL) || (strcmp( value, proto ) == 0);
344 }
345
346 #endif /* PKGBASE_H: $RCSfile$: end of file */