From: James Turner <zakalawe@mac.com>
Date: Mon, 28 Sep 2015 00:42:08 +0000 (-0500)
Subject: Package support progress
X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=4e40913aefd3dd5c031eda47f15b76a12c0f5ae2;p=simgear.git

Package support progress

- check the catalog version explicitly when refreshing
- handle packages with distinct dir name / primary ID correctly
  (requires an updated catalog XML format)
---

diff --git a/simgear/package/Catalog.cxx b/simgear/package/Catalog.cxx
index 5d407fe5..1a810af8 100644
--- a/simgear/package/Catalog.cxx
+++ b/simgear/package/Catalog.cxx
@@ -90,8 +90,13 @@ protected:
     virtual void onDone()
     {
         if (responseCode() != 200) {
-            SG_LOG(SG_GENERAL, SG_ALERT, "catalog download failure:" << m_owner->url());
-            m_owner->refreshComplete(Delegate::FAIL_DOWNLOAD);
+            Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD;
+            SG_LOG(SG_GENERAL, SG_ALERT, "catalog download failure:" << m_owner->url()
+                   << "\n\t" << responseCode());
+            if (responseCode() == 404) {
+                code = Delegate::FAIL_NOT_FOUND;
+            }
+            m_owner->refreshComplete(code);
             return;
         }
 
@@ -106,7 +111,15 @@ protected:
             return;
         }
 
-        std::string ver(m_owner->root()->catalogVersion());
+        if (m_owner->root()->catalogVersion() != props->getIntValue("catalog-version")) {
+            SG_LOG(SG_GENERAL, SG_WARN, "catalog:" << m_owner->url() << " is not version "
+                   << m_owner->root()->catalogVersion());
+            m_owner->refreshComplete(Delegate::FAIL_VERSION);
+            return;
+        }
+
+
+        std::string ver(m_owner->root()->applicationVersion());
         if (!checkVersion(ver, props)) {
             SG_LOG(SG_GENERAL, SG_WARN, "downloaded catalog " << m_owner->url() << ", version mismatch:\n\t"
                    << props->getStringValue("version") << " vs required " << ver);
@@ -186,8 +199,8 @@ CatalogRef Catalog::createFromPath(Root* aRoot, const SGPath& aPath)
         return NULL;
     }
 
-    if (!checkVersion(aRoot->catalogVersion(), props)) {
-        std::string redirect = redirectUrlForVersion(aRoot->catalogVersion(), props);
+    if (!checkVersion(aRoot->applicationVersion(), props)) {
+        std::string redirect = redirectUrlForVersion(aRoot->applicationVersion(), props);
         if (!redirect.empty()) {
             SG_LOG(SG_GENERAL, SG_WARN, "catalog at " << aPath << ", version mismatch:\n\t"
                    << "redirecting to alternate URL:" << redirect);
@@ -385,11 +398,23 @@ PackageRef Catalog::getPackageById(const std::string& aId) const
     // works as expected.
     PackageWeakMap::const_iterator it = m_variantDict.find(aId);
     if (it == m_variantDict.end())
-        return NULL;
+        return PackageRef();
 
     return it->second;
 }
 
+PackageRef Catalog::getPackageByPath(const std::string& aPath) const
+{
+    PackageList::const_iterator it;
+    for (it = m_packages.begin(); it != m_packages.end(); ++it) {
+        if ((*it)->dirName() == aPath) {
+            return *it;
+        }
+    }
+
+    return PackageRef();
+}
+
 std::string Catalog::id() const
 {
     return m_props->getStringValue("id");
diff --git a/simgear/package/Catalog.hxx b/simgear/package/Catalog.hxx
index e21df6a1..65e3f992 100644
--- a/simgear/package/Catalog.hxx
+++ b/simgear/package/Catalog.hxx
@@ -109,6 +109,8 @@ public:
 
     PackageRef getPackageById(const std::string& aId) const;
 
+    PackageRef getPackageByPath(const std::string& aPath) const;
+
     /**
      * test if the catalog data was retrieved longer ago than the
      * maximum permitted age for this catalog.
diff --git a/simgear/package/Delegate.hxx b/simgear/package/Delegate.hxx
index 145f6a2e..8de67aa5 100644
--- a/simgear/package/Delegate.hxx
+++ b/simgear/package/Delegate.hxx
@@ -44,11 +44,12 @@ public:
         STATUS_SUCCESS = 0,
         FAIL_UNKNOWN = 1,
         STATUS_IN_PROGRESS, ///< downloading/installation in progress
-        FAIL_CHECKSUM,  ///< package MD5 verificstion failed
-        FAIL_DOWNLOAD,  ///< network issue
-        FAIL_EXTRACT,   ///< package archive failed to extract cleanly
+        FAIL_CHECKSUM,      ///< package MD5 verificstion failed
+        FAIL_DOWNLOAD,      ///< network issue
+        FAIL_EXTRACT,       ///< package archive failed to extract cleanly
         FAIL_FILESYSTEM,    ///< unknown filesystem error occurred
-        FAIL_VERSION, ///< version check mismatch
+        FAIL_VERSION,       ///< version check mismatch
+        FAIL_NOT_FOUND,     ///< package URL returned a 404
         STATUS_REFRESHED,
         USER_CANCELLED
     } StatusCode;
diff --git a/simgear/package/Install.cxx b/simgear/package/Install.cxx
index 0217e457..b91d2552 100644
--- a/simgear/package/Install.cxx
+++ b/simgear/package/Install.cxx
@@ -106,8 +106,14 @@ protected:
     virtual void onDone()
     {
         if (responseCode() != 200) {
-            SG_LOG(SG_GENERAL, SG_ALERT, "download failure");
-            doFailure(Delegate::FAIL_DOWNLOAD);
+            SG_LOG(SG_GENERAL, SG_ALERT, "download failure:" << responseCode() <<
+                   "\n\t" << url());
+            Delegate::StatusCode code = Delegate::FAIL_DOWNLOAD;
+            if (responseCode() == 404) {
+                code = Delegate::FAIL_NOT_FOUND;
+            }
+
+            doFailure(code);
             return;
         }
 
@@ -137,7 +143,7 @@ protected:
             destDir.remove(true /* recursive */);
         }
 
-        m_extractPath.append(m_owner->package()->id());
+        m_extractPath.append(m_owner->package()->dirName());
         bool ok = m_extractPath.rename(m_owner->path());
         if (!ok) {
             doFailure(Delegate::FAIL_FILESYSTEM);
@@ -296,10 +302,10 @@ Install::~Install()
 
 InstallRef Install::createFromPath(const SGPath& aPath, CatalogRef aCat)
 {
-    std::string id = aPath.file();
-    PackageRef pkg = aCat->getPackageById(id);
+    std::string path = aPath.file();
+    PackageRef pkg = aCat->getPackageByPath(path);
     if (!pkg)
-        throw sg_exception("no package with id:" + id);
+        throw sg_exception("no package with path:" + path);
 
     return new Install(pkg, aPath);
 }
diff --git a/simgear/package/Package.cxx b/simgear/package/Package.cxx
index 5f76d746..bd25fb3c 100644
--- a/simgear/package/Package.cxx
+++ b/simgear/package/Package.cxx
@@ -117,7 +117,7 @@ SGPath Package::pathOnDisk() const
 {
     SGPath p(m_catalog->installRoot());
     p.append("Aircraft");
-    p.append(id());
+    p.append(dirName());
     return p;
 }
 
@@ -139,7 +139,12 @@ InstallRef Package::install()
 
 InstallRef Package::existingInstall(const InstallCallback& cb) const
 {
-  InstallRef install = m_catalog->root()->existingInstallForPackage(const_cast<Package*>(this));
+    InstallRef install;
+    try {
+        install = m_catalog->root()->existingInstallForPackage(const_cast<Package*>(this));
+    } catch (std::exception& e) {
+        return InstallRef();
+    }
 
   if( cb )
   {
@@ -167,6 +172,14 @@ std::string Package::md5() const
     return m_props->getStringValue("md5");
 }
 
+std::string Package::dirName() const
+{
+    std::string r(m_props->getStringValue("dir"));
+    if (r.empty())
+        throw sg_exception("missing dir property on catalog package entry for " + m_id);
+    return r;
+}
+
 unsigned int Package::revision() const
 {
     if (!m_props) {
diff --git a/simgear/package/Package.hxx b/simgear/package/Package.hxx
index 9293ca0d..606185fd 100644
--- a/simgear/package/Package.hxx
+++ b/simgear/package/Package.hxx
@@ -133,6 +133,12 @@ public:
      * this will raise an sg_exception.
      */
     PackageList dependencies() const;
+
+    /**
+     * Name of the package directory on disk. This may or may not be the
+     * same as the primary ID, depending on the aircraft author
+     */
+    std::string dirName() const;
 private:
     SGPath pathOnDisk() const;
 
diff --git a/simgear/package/Root.cxx b/simgear/package/Root.cxx
index a0bef7c3..2fca504f 100644
--- a/simgear/package/Root.cxx
+++ b/simgear/package/Root.cxx
@@ -246,8 +246,13 @@ Root::~Root()
 {
     
 }
+
+int Root::catalogVersion() const
+{
+    return 4;
+}
     
-std::string Root::catalogVersion() const
+std::string Root::applicationVersion() const
 {
     return d->version;
 }
@@ -442,11 +447,13 @@ void Root::finishInstall(InstallRef aInstall, Delegate::StatusCode aReason)
         SG_LOG(SG_GENERAL, SG_ALERT, "failed to install package:"
                << aInstall->package()->id() << ":" << aReason);
     }
-    
-    d->fireFinishInstall(aInstall, aReason);
+
+    // order matters here, so a call to 'isQueued' from a finish-install
+    // callback returns false, not true
     startNext(aInstall);
+    d->fireFinishInstall(aInstall, aReason);
 }
-    
+
 void Root::cancelDownload(InstallRef aInstall)
 {
     RootPrivate::UpdateDeque::iterator it =
@@ -544,7 +551,10 @@ InstallRef Root::existingInstallForPackage(PackageRef p) const
             // this will add to our cache, and hence, modify m_installs
             return Install::createFromPath(path, p->catalog());
         }
- 
+
+        // insert a null reference into the dictionary, so we don't call
+        // the pathOnDisk -> exists codepath repeatedley
+        d->m_installs[p] = InstallRef();
         return InstallRef();
     }
     
diff --git a/simgear/package/Root.hxx b/simgear/package/Root.hxx
index 11e9a647..eadfac88 100644
--- a/simgear/package/Root.hxx
+++ b/simgear/package/Root.hxx
@@ -83,11 +83,17 @@ public:
     void makeHTTPRequest(HTTP::Request* req);
     
     /**
-     * the version string of the root. Catalogs must match this version,
+     * The catalog XML/property version in use. This is used to make incomaptible
+     * changes to the package/catalog syntax
+     */
+    int catalogVersion() const;
+
+    /**
+     * the version string of the application. Catalogs must match this version,
      * or they will be ignored / rejected.
      */
-    std::string catalogVersion() const;
-    
+    std::string applicationVersion() const;
+
     /**
      * refresh catalogs which are more than the maximum age (24 hours by default)
      * set force to true, to download all catalogs regardless of age.