changeset 188:07b908b4fa5f

* Set python library path when unbundling extension, generally prefer unbundled copy
author Chris Cannam
date Mon, 20 Dec 2010 16:15:43 +0000
parents 869825bc8bc4
children 6bb510abe4f1
files easyhg.py hgrunner.cpp hgrunner.h
diffstat 3 files changed, 80 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/easyhg.py	Mon Dec 20 16:15:19 2010 +0000
+++ b/easyhg.py	Mon Dec 20 16:15:43 2010 +0000
@@ -16,6 +16,16 @@
 import sys
 from mercurial import ui, getpass, util
 from mercurial.i18n import _
+
+# The value assigned here may be modified during installation, by
+# replacing its default value with another one.  We can't compare
+# against its default value, because then the comparison text would
+# get modified as well.  So, compare using prefix only.
+#
+easyhg_import_path = 'NO_EASYHG_IMPORT_PATH'
+if not easyhg_import_path.startswith('NO_'):
+    sys.path.append(easyhg_import_path)
+
 from PyQt4 import QtGui
 
 easyhg_qtapp = None
--- a/hgrunner.cpp	Mon Dec 20 16:15:19 2010 +0000
+++ b/hgrunner.cpp	Mon Dec 20 16:15:43 2010 +0000
@@ -26,6 +26,7 @@
 #include <QVBoxLayout>
 #include <QSettings>
 #include <QInputDialog>
+#include <QTemporaryFile>
 #include <QDir>
 
 #include <iostream>
@@ -64,44 +65,96 @@
 
 QString HgRunner::findExtension()
 {
+    // If we haven't unbundled an extension, always do that (so that
+    // it's available in case someone wants to use it later, e.g. to
+    // fix a malfunctioning setup).  But the path we actually prefer
+    // is the one in the settings first; then the unbundled one; then
+    // anything in the path if for some reason unbundling failed
+
     QSettings settings;
     settings.beginGroup("Locations");
+
+    QString unbundled = getUnbundledFileName();
+    if (!QFile(unbundled).exists()) {
+        unbundled = unbundleExtension();
+    }
+
     QString extpath = settings.value("extensionpath", "").toString();
     if (extpath != "") return extpath;
-    extpath = findInPath("easyhg.py", m_myDirPath, false);
-    if (extpath == "easyhg.py") {
-        extpath = unbundleExtension();
+
+    extpath = unbundled;
+    if (extpath == "") {
+        extpath = findInPath("easyhg.py", m_myDirPath, false);
+        if (extpath == "easyhg.py") {
+            extpath = "";
+        }
     }
+
     settings.setValue("extensionpath", extpath);
     return extpath;
 }   
 
+QString HgRunner::getUnbundledFileName()
+{
+    QString home = QDir::homePath();
+    QString target = QString("%1/.easyhg").arg(home);
+    QString extpath = QString("%1/easyhg.py").arg(target);
+    return extpath;
+}
+
 QString HgRunner::unbundleExtension()
 {
+    // Pull out the bundled Python file into a temporary file, and
+    // copy it to our known extension location, replacing the magic
+    // text NO_EASYHG_IMPORT_PATH with our installation location
+
     QString bundled = ":easyhg.py";
-    QString home = QDir::homePath();
-    QString target = QString("%1/.easyhg").arg(home);
+    QString unbundled = getUnbundledFileName();
+
+    QString target = QFileInfo(unbundled).path();
     if (!QDir().mkpath(target)) {
         DEBUG << "Failed to make unbundle path " << target << endl;
-        std::cerr << "Failed to make unbundle path " << target.toStdString() << std::endl;
+        std::cerr << "Failed to make unbundle path " << target << std::endl;
         return ""; 
     }
+
     QFile bf(bundled);
-    if (!bf.exists()) {
+    DEBUG << "unbundle: bundled file will be " << bundled << endl;
+    if (!bf.exists() || !bf.open(QIODevice::ReadOnly)) {
         DEBUG << "Bundled extension is missing!" << endl;
         return "";
     }
-    QString extpath = QString("%1/easyhg.py").arg(target);
-    if (QFile(extpath).exists()) {
-        QFile(extpath).remove();
-    }
-    if (!bf.copy(extpath)) {
-        DEBUG << "Failed to unbundle extension to " << target << endl;
-        std::cerr << "Failed to unbundle extension to " << extpath.toStdString() << std::endl;
+
+    QTemporaryFile tmpfile(QString("%1/easyhg.py.XXXXXX").arg(target));
+    tmpfile.setAutoRemove(false);
+    DEBUG << "unbundle: temp file will be " << tmpfile.fileName() << endl;
+    if (!tmpfile.open()) {
+        DEBUG << "Failed to open temporary file " << tmpfile.fileName() << endl;
+        std::cerr << "Failed to open temporary file " << tmpfile.fileName() << std::endl;
         return "";
     }
-    DEBUG << "Unbundled extension to " << extpath << endl;
-    return extpath;
+
+    QString all = QString::fromUtf8(bf.readAll());
+    all.replace("NO_EASYHG_IMPORT_PATH", m_myDirPath);
+    tmpfile.write(all.toUtf8());
+    DEBUG << "unbundle: wrote " << all.length() << " characters" << endl;
+
+    tmpfile.close();
+
+    QFile ef(unbundled);
+    if (ef.exists()) {
+        DEBUG << "unbundle: removing old file " << unbundled << endl;
+        ef.remove();
+    }
+    DEBUG << "unbundle: renaming " << tmpfile.fileName() << " to " << unbundled << endl;
+    if (!tmpfile.rename(unbundled)) {
+        DEBUG << "Failed to move temporary file to target file " << unbundled << endl;
+        std::cerr << "Failed to move temporary file to target file " << unbundled << std::endl;
+        return "";
+    }
+    
+    DEBUG << "Unbundled extension to " << unbundled << endl;
+    return unbundled;
 }        
 
 void HgRunner::requestAction(HgAction action)
--- a/hgrunner.h	Mon Dec 20 16:15:19 2010 +0000
+++ b/hgrunner.h	Mon Dec 20 16:15:43 2010 +0000
@@ -67,6 +67,7 @@
 
     QString findExtension();
     QString findHgBinaryName();
+    QString getUnbundledFileName();
     QString unbundleExtension();
 
     int m_ptyMasterFd;