OSDN Git Service

Implement package installer for tar archives.
[mingw/mingw-get.git] / src / pkgbind.cpp
1 /*
2  * pkgbind.cpp
3  *
4  * $Id$
5  *
6  * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
7  * Copyright (C) 2009, 2010, MinGW Project
8  *
9  *
10  * Implementation of repository binding for the pkgXmlDocument class.
11  *
12  *
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.
18  *
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.
25  *
26  */
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31
32 #include "dmh.h"
33 #include "pkgbase.h"
34 #include "pkgkeys.h"
35
36 pkgXmlNode *pkgXmlDocument::BindRepositories( bool force_update )
37 {
38   /* Identify the repositories specified in the application profile,
39    * and merge their associated package distribution lists into the
40    * active XML database, which is bound to the profile.
41    */
42   pkgXmlNode *dbase = GetRoot();
43
44   /* Before blindly proceeding, perform a sanity check...
45    * Verify that this XML database defines an application profile,
46    * and that the associated application is "mingw-get"...
47    */
48   if( (strcmp( dbase->GetName(), profile_key ) == 0)
49   &&  (strcmp( dbase->GetPropVal( application_key, "?" ), "mingw-get") == 0) )
50   {
51     /* Sanity check passed...
52      * Walk the XML data tree, selecting "repository" specifications...
53      */
54     pkgXmlNode *repository = dbase->FindFirstAssociate( repository_key );
55     while( repository != NULL )
56     {
57       /* For each "repository" specified, identify its "catalogues"...
58        *
59        * FIXME: this requires the "package-lists" to be individually
60        * specified within the locally defined "repository" elements;
61        * it should allow for deduction of these, from a specifically
62        * named "repository-index" file identified via the repository
63        * URI template, and hosted by the download server itself.
64        */
65       pkgXmlNode *catalogue = repository->FindFirstAssociate( package_list_key );
66       while( catalogue != NULL )
67       {
68         /* ...and for each named "catalogue"...
69          */
70         const char *dfile, *dname = catalogue->GetPropVal( catalogue_key, NULL );
71         if( (dname != NULL) && ((dfile = xmlfile( dname )) != NULL) )
72         {
73           /* Check for a locally cached copy of the "package-list" file...
74            */
75           if( force_update || (access( dfile, F_OK ) != 0) )
76             /*
77              * When performing an "update", or if no local copy is available...
78              * Force a "sync", to fetch a copy from the public host.
79              */
80             SyncRepository( dname, repository );
81
82           /* We SHOULD now have a locally cached copy of the package-list;
83            * attempt to merge it into the active profile database...
84            */
85           pkgXmlDocument merge( dfile );
86           if( merge.IsOk() )
87           {
88             /* We successfully loaded the XML catalogue; refer to its
89              * root element...
90              */
91             dmh_printf( "Bind repository: %s\n", merge.Value() );
92             pkgXmlNode *pkglist;
93             if( (pkglist = merge.GetRoot()) != NULL )
94             {
95               /* ...read it, selecting each of the "package-collection"
96                * records contained within it...
97                */
98               pkglist = pkglist->FindFirstAssociate( package_collection_key );
99               while( pkglist != NULL )
100               {
101                 /* ...and append a copy of each to the active profile...
102                  */
103                 dbase->LinkEndChild( pkglist->Clone() );
104
105                 /* Move on to the next "package-collection" (if any)
106                  * within the current catalogue...
107                  */
108                 pkglist = pkglist->FindNextAssociate( package_collection_key );
109               }
110             }
111           }
112           else
113             dmh_notify( DMH_WARNING, "Bind repository: FAILED: %s\n", dfile );
114
115           /* However we handled it, the XML file's path name in "dfile" was
116            * allocated on the heap; we lose its reference on termination of
117            * this loop, so we must free it to avoid a memory leak.
118            */
119           free( (void *)(dfile) );
120         }
121
122         /* A repository may comprise an arbitrary collection of software
123          * catalogues; move on, to process the next catalogue (if any) in
124          * the current repository collection.
125          */
126         catalogue = catalogue->FindNextAssociate( package_list_key );
127       }
128
129       /* Similarly, a complete distribution may draw from an arbitrary set
130        * of distinct repositories; move on, to process the next repository
131        * specified (if any).
132        */
133       repository = repository->FindNextAssociate( repository_key );
134     }
135
136     /* On successful completion, return a pointer to the root node
137      * of the active XML profile.
138      */
139     return dbase;
140   }
141
142   /* Fall through on total failure to interpret the profile, returning
143    * NULL to indicate failure.
144    */
145   return NULL;
146 }
147
148 /* $RCSfile$: end of file */