]> git.mxchange.org Git - simgear.git/commitdiff
Package support progress
authorJames Turner <zakalawe@mac.com>
Mon, 28 Sep 2015 00:42:08 +0000 (19:42 -0500)
committerJames Turner <zakalawe@mac.com>
Mon, 28 Sep 2015 00:42:08 +0000 (19:42 -0500)
- check the catalog version explicitly when refreshing
- handle packages with distinct dir name / primary ID correctly
  (requires an updated catalog XML format)

simgear/package/Catalog.cxx
simgear/package/Catalog.hxx
simgear/package/Delegate.hxx
simgear/package/Install.cxx
simgear/package/Package.cxx
simgear/package/Package.hxx
simgear/package/Root.cxx
simgear/package/Root.hxx

index 5d407fe5b1bc500dd7c957900db302b66e88fbd8..1a810af8a7c00b76782b5728e0363e7c1a7c498d 100644 (file)
@@ -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");
index e21df6a1a4129b3f0a057407e98c9a6075435d4b..65e3f992ec06d544d7b66d7382b10a144a6de08c 100644 (file)
@@ -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.
index 145f6a2ee202ee032a5f517bb203a9d21809957f..8de67aa53c75fcbbbbca1309cfd7b50178a2ee94 100644 (file)
@@ -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;
index 0217e457f4c11b11de0f8f53fc52a77b67945d22..b91d2552e79a63dce70de23fd88ae9d2ae903346 100644 (file)
@@ -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);
 }
index 5f76d746b98adb437ef487f74b31f7c0eb0bca68..bd25fb3c60726f2af504028a9b0d2c7a4ee6fc11 100644 (file)
@@ -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) {
index 9293ca0d649eefb80125975e93f281d5a97ca03c..606185fdddcafb6ffe0a451e5ff4af71f8022824 100644 (file)
@@ -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;
 
index a0bef7c3496ad43ba2ba97badd568f9759e5f2a8..2fca504fdc380a7a41428217527562b3fbc1666a 100644 (file)
@@ -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();
     }
     
index 11e9a647a8bfcc3e984a20a8a2bed21b7fb6b8e4..eadfac8847dc0f58b874c8deeb358f7186b83cc4 100644 (file)
@@ -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.