OSDN Git Service

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