#include <simgear/package/Package.hxx>
+#include <cassert>
#include <boost/foreach.hpp>
#include <simgear/debug/logstream.hxx>
+#include <simgear/structure/exception.hxx>
+
#include <simgear/package/Catalog.hxx>
#include <simgear/package/Install.hxx>
#include <simgear/package/Root.hxx>
{
return m_props->getIntValue("revision");
}
+
+SGPropertyNode* Package::properties() const
+{
+ return m_props.ptr();
+}
+
+string_list Package::thumbnailUrls() const
+{
+ string_list r;
+ BOOST_FOREACH(SGPropertyNode* dl, m_props->getChildren("thumbnail")) {
+ r.push_back(dl->getStringValue());
+ }
+ return r;
+}
string_list Package::downloadUrls() const
{
return aRoot->getStringValue(aName);
}
+PackageList Package::dependencies() const
+{
+ PackageList result;
+
+ BOOST_FOREACH(SGPropertyNode* dep, m_props->getChildren("depends")) {
+ std::string depName = dep->getStringValue("package");
+ unsigned int rev = dep->getIntValue("revision", 0);
+
+ // prefer local hangar package if possible, in case someone does something
+ // silly with naming. Of course flightgear's aircraft search doesn't know
+ // about hanagrs, so names still need to be unique.
+ Package* depPkg = m_catalog->getPackageById(depName);
+ if (!depPkg) {
+ Root* rt = m_catalog->root();
+ depPkg = rt->getPackageById(depName);
+ if (!depPkg) {
+ throw sg_exception("Couldn't satisfy dependency of " + id() + " : " + depName);
+ }
+ }
+
+ if (depPkg->revision() < rev) {
+ throw sg_range_exception("Couldn't find suitable revision of " + depName);
+ }
+
+ // forbid recursive dependency graphs, we don't need that level
+ // of complexity for aircraft resources
+ assert(depPkg->dependencies() == PackageList());
+
+ result.push_back(depPkg);
+ }
+
+ return result;
+}
+
} // of namespace pkg
} // of namespace simgear
// forward decls
class Install;
class Catalog;
+class Package;
+typedef std::vector<Package*> PackageList;
+
class Package
{
public:
std::string id() const;
+ /**
+ * access the raw property data in the package
+ */
+ SGPropertyNode* properties() const;
+
+ /**
+ * hex-encoded MD5 sum of the download files
+ */
std::string md5() const;
std::string getLocalisedProp(const std::string& aName) const;
bool matches(const SGPropertyNode* aFilter) const;
+ /**
+ * download URLs for the package
+ */
string_list downloadUrls() const;
+
+ string_list thumbnailUrls() const;
+
+ /**
+ * Packages we depend upon.
+ * If the dependency list cannot be satisifed for some reason,
+ * this will raise an sg_exception.
+ */
+ PackageList dependencies() const;
private:
friend class Catalog;
Catalog* m_catalog;
};
-typedef std::vector<Package*> PackageList;
+
} // of namespace pkg
void Root::scheduleToUpdate(Install* aInstall)
{
- bool wasEmpty = m_updateDeque.empty();
+ if (!aInstall) {
+ sg_exception("missing argument to scheduleToUpdate");
+ }
+
+ PackageList deps = aInstall->package()->dependencies();
+ BOOST_FOREACH(Package* dep, deps) {
+ // will internally schedule for update if required
+ // hence be careful, this method is re-entered in here!
+ dep->install();
+ }
+
+ bool wasEmpty = m_updateDeque.empty();
m_updateDeque.push_back(aInstall);
if (wasEmpty) {
aInstall->startUpdate();