From 04160f2ca160881256d2de9d9ecf59877106f885 Mon Sep 17 00:00:00 2001
From: David Kelly <david@highfidelity.io>
Date: Fri, 23 Jun 2017 09:19:41 -0700
Subject: [PATCH 1/3] switch to change ktx_cache directory (only)

---
 interface/src/main.cpp             | 10 ++++++++--
 libraries/shared/src/PathUtils.cpp | 15 ++++++++++++++-
 libraries/shared/src/PathUtils.h   |  2 +-
 3 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/interface/src/main.cpp b/interface/src/main.cpp
index 83cac6d9bb..0ab00b1e57 100644
--- a/interface/src/main.cpp
+++ b/interface/src/main.cpp
@@ -71,15 +71,17 @@ int main(int argc, const char* argv[]) {
     QCommandLineOption runServerOption("runServer", "Whether to run the server");
     QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath");
     QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run");
+    QCommandLineOption overrideAppLocalDataPathOption("cache", "Override cache directory", "value");
     parser.addOption(urlOption);
     parser.addOption(noUpdaterOption);
     parser.addOption(checkMinSpecOption);
     parser.addOption(runServerOption);
     parser.addOption(serverContentPathOption);
+    parser.addOption(overrideAppLocalDataPathOption);
     parser.addOption(allowMultipleInstancesOption);
     parser.parse(arguments);
 
-    
+
     const QString& applicationName = getInterfaceSharedMemoryName();
     bool instanceMightBeRunning = true;
 #ifdef Q_OS_WIN
@@ -96,6 +98,10 @@ int main(int argc, const char* argv[]) {
     if (allowMultipleInstances) {
         instanceMightBeRunning = false;
     }
+    if (parser.isSet(overrideAppLocalDataPathOption)) {
+        QString appLocalDataPath = parser.value(overrideAppLocalDataPathOption);
+        PathUtils::getAppLocalDataPath(appLocalDataPath);
+    }
 
     if (instanceMightBeRunning) {
         // Try to connect and send message to existing interface instance
@@ -179,7 +185,7 @@ int main(int argc, const char* argv[]) {
         QString openvrDllPath = appPath + "/plugins/openvr.dll";
         HMODULE openvrDll;
         CHECKMINSPECPROC checkMinSpecPtr;
-        if ((openvrDll = LoadLibrary(openvrDllPath.toLocal8Bit().data())) && 
+        if ((openvrDll = LoadLibrary(openvrDllPath.toLocal8Bit().data())) &&
             (checkMinSpecPtr = (CHECKMINSPECPROC)GetProcAddress(openvrDll, "CheckMinSpec"))) {
             if (!checkMinSpecPtr()) {
                 return -1;
diff --git a/libraries/shared/src/PathUtils.cpp b/libraries/shared/src/PathUtils.cpp
index 9bf9d7bdcf..63a94c1696 100644
--- a/libraries/shared/src/PathUtils.cpp
+++ b/libraries/shared/src/PathUtils.cpp
@@ -34,7 +34,20 @@ QString PathUtils::getAppDataPath() {
     return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/";
 }
 
-QString PathUtils::getAppLocalDataPath() {
+QString PathUtils::getAppLocalDataPath(const QString& overridePath) {
+    static QString overriddenPath = "";
+
+    // set the overridden path if one was passed in
+    if (!overridePath.isEmpty()) {
+        overriddenPath = overridePath;
+    }
+
+    // return overridden path if there is one
+    if (!overriddenPath.isEmpty()) {
+        return overriddenPath;
+    }
+
+    // otherwise return the standard path
     return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/";
 }
 
diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h
index 14eb81dd9a..1160fd8106 100644
--- a/libraries/shared/src/PathUtils.h
+++ b/libraries/shared/src/PathUtils.h
@@ -28,7 +28,7 @@ public:
     static const QString& resourcesPath();
 
     static QString getAppDataPath();
-    static QString getAppLocalDataPath();
+    static QString getAppLocalDataPath(const QString& overrideDataPath = "");
 
     static QString getAppDataFilePath(const QString& filename);
     static QString getAppLocalDataFilePath(const QString& filename);

From bda50af78098ea0fd549a201bcd0622906ecd23e Mon Sep 17 00:00:00 2001
From: David Kelly <david@highfidelity.io>
Date: Fri, 23 Jun 2017 11:06:48 -0700
Subject: [PATCH 2/3] this uses qt's test location for AppData/Local, but
 leaves Roaming alone

---
 interface/src/main.cpp             | 12 +++++++++---
 libraries/shared/src/PathUtils.cpp | 15 +--------------
 libraries/shared/src/PathUtils.h   |  2 +-
 3 files changed, 11 insertions(+), 18 deletions(-)

diff --git a/interface/src/main.cpp b/interface/src/main.cpp
index 0ab00b1e57..81bf0244d9 100644
--- a/interface/src/main.cpp
+++ b/interface/src/main.cpp
@@ -71,7 +71,7 @@ int main(int argc, const char* argv[]) {
     QCommandLineOption runServerOption("runServer", "Whether to run the server");
     QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath");
     QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run");
-    QCommandLineOption overrideAppLocalDataPathOption("cache", "Override cache directory", "value");
+    QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache directory");
     parser.addOption(urlOption);
     parser.addOption(noUpdaterOption);
     parser.addOption(checkMinSpecOption);
@@ -99,8 +99,14 @@ int main(int argc, const char* argv[]) {
         instanceMightBeRunning = false;
     }
     if (parser.isSet(overrideAppLocalDataPathOption)) {
-        QString appLocalDataPath = parser.value(overrideAppLocalDataPathOption);
-        PathUtils::getAppLocalDataPath(appLocalDataPath);
+        // get standard path
+        auto standardAppDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
+        // set to test so all future paths are the test paths
+        QStandardPaths::setTestModeEnabled(true);
+        // now, we need to link everything in AppDataLocation to the test AppDataLocation.  This
+        // leaves the test location for AppLocalDataLocation alone, but allows all the stuff in
+        // AppDataLocation to be usable
+        QFile::link(standardAppDataLocation, QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
     }
 
     if (instanceMightBeRunning) {
diff --git a/libraries/shared/src/PathUtils.cpp b/libraries/shared/src/PathUtils.cpp
index 63a94c1696..9bf9d7bdcf 100644
--- a/libraries/shared/src/PathUtils.cpp
+++ b/libraries/shared/src/PathUtils.cpp
@@ -34,20 +34,7 @@ QString PathUtils::getAppDataPath() {
     return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/";
 }
 
-QString PathUtils::getAppLocalDataPath(const QString& overridePath) {
-    static QString overriddenPath = "";
-
-    // set the overridden path if one was passed in
-    if (!overridePath.isEmpty()) {
-        overriddenPath = overridePath;
-    }
-
-    // return overridden path if there is one
-    if (!overriddenPath.isEmpty()) {
-        return overriddenPath;
-    }
-
-    // otherwise return the standard path
+QString PathUtils::getAppLocalDataPath() {
     return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/";
 }
 
diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h
index 1160fd8106..14eb81dd9a 100644
--- a/libraries/shared/src/PathUtils.h
+++ b/libraries/shared/src/PathUtils.h
@@ -28,7 +28,7 @@ public:
     static const QString& resourcesPath();
 
     static QString getAppDataPath();
-    static QString getAppLocalDataPath(const QString& overrideDataPath = "");
+    static QString getAppLocalDataPath();
 
     static QString getAppDataFilePath(const QString& filename);
     static QString getAppLocalDataFilePath(const QString& filename);

From 01155ba4e38e90800650a5a2324a61eeae61b15f Mon Sep 17 00:00:00 2001
From: David Kelly <david@highfidelity.io>
Date: Tue, 27 Jun 2017 08:47:54 -0700
Subject: [PATCH 3/3] this handles redirecting ktx_cache, data8, prepared

---
 interface/src/Application.cpp                |  2 --
 interface/src/Application.h                  |  3 +++
 interface/src/main.cpp                       | 22 ++++++++++++--------
 libraries/networking/src/AssetClient.cpp     | 13 ++++++------
 libraries/networking/src/AssetClient.h       |  4 +++-
 libraries/networking/src/ResourceManager.cpp |  8 +++++--
 libraries/networking/src/ResourceManager.h   |  5 +++++
 libraries/shared/src/PathUtils.cpp           | 13 +++++++++++-
 libraries/shared/src/PathUtils.h             |  2 +-
 9 files changed, 50 insertions(+), 22 deletions(-)

diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 35d00ba34a..9052f082dc 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -37,8 +37,6 @@
 #include <QtQml/QQmlEngine>
 #include <QtQuick/QQuickWindow>
 
-#include <QtWebEngineWidgets/QWebEngineProfile>
-
 #include <QtWidgets/QDesktopWidget>
 #include <QtWidgets/QMessageBox>
 
diff --git a/interface/src/Application.h b/interface/src/Application.h
index cab42d1e1c..a7aded006b 100644
--- a/interface/src/Application.h
+++ b/interface/src/Application.h
@@ -297,6 +297,7 @@ public:
     void setAvatarOverrideUrl(const QUrl& url, bool save);
     QUrl getAvatarOverrideUrl() { return _avatarOverrideUrl; }
     bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; }
+    void setCacheOverrideDir(const QString& dirName) { _cacheDir = dirName; }
 
 signals:
     void svoImportRequested(const QString& url);
@@ -688,5 +689,7 @@ private:
 
     QUrl _avatarOverrideUrl;
     bool _saveAvatarOverrideUrl { false };
+
+    QString _cacheDir;
 };
 #endif // hifi_Application_h
diff --git a/interface/src/main.cpp b/interface/src/main.cpp
index 81bf0244d9..67e248506f 100644
--- a/interface/src/main.cpp
+++ b/interface/src/main.cpp
@@ -23,6 +23,7 @@
 #include <gl/OpenGLVersionChecker.h>
 #include <SandboxUtils.h>
 #include <SharedUtil.h>
+#include <NetworkAccessManager.h>
 
 #include "AddressManager.h"
 #include "Application.h"
@@ -71,7 +72,7 @@ int main(int argc, const char* argv[]) {
     QCommandLineOption runServerOption("runServer", "Whether to run the server");
     QCommandLineOption serverContentPathOption("serverContentPath", "Where to find server content", "serverContentPath");
     QCommandLineOption allowMultipleInstancesOption("allowMultipleInstances", "Allow multiple instances to run");
-    QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache directory");
+    QCommandLineOption overrideAppLocalDataPathOption("cache", "set test cache <dir>", "dir");
     parser.addOption(urlOption);
     parser.addOption(noUpdaterOption);
     parser.addOption(checkMinSpecOption);
@@ -99,14 +100,17 @@ int main(int argc, const char* argv[]) {
         instanceMightBeRunning = false;
     }
     if (parser.isSet(overrideAppLocalDataPathOption)) {
-        // get standard path
-        auto standardAppDataLocation = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
-        // set to test so all future paths are the test paths
-        QStandardPaths::setTestModeEnabled(true);
-        // now, we need to link everything in AppDataLocation to the test AppDataLocation.  This
-        // leaves the test location for AppLocalDataLocation alone, but allows all the stuff in
-        // AppDataLocation to be usable
-        QFile::link(standardAppDataLocation, QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
+        // get dir to use for cache
+        QString cacheDir = parser.value(overrideAppLocalDataPathOption);
+        if (!cacheDir.isEmpty()) {
+            // tell everyone to use the right cache location
+            //
+            // this handles data8 and prepared
+            ResourceManager::setCacheDir(cacheDir);
+
+            // this does the ktx_cache
+            PathUtils::getAppLocalDataPath(cacheDir);
+        }
     }
 
     if (instanceMightBeRunning) {
diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp
index 3faa9981dc..e97660da4c 100644
--- a/libraries/networking/src/AssetClient.cpp
+++ b/libraries/networking/src/AssetClient.cpp
@@ -31,7 +31,7 @@
 
 MessageID AssetClient::_currentID = 0;
 
-AssetClient::AssetClient() {
+AssetClient::AssetClient(const QString& cacheDir) : _cacheDir(cacheDir) {
     setCustomDeleter([](Dependency* dependency){
         static_cast<AssetClient*>(dependency)->deleteLater();
     });
@@ -55,14 +55,15 @@ void AssetClient::init() {
     // Setup disk cache if not already
     auto& networkAccessManager = NetworkAccessManager::getInstance();
     if (!networkAccessManager.cache()) {
-        QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
-        cachePath = !cachePath.isEmpty() ? cachePath : "interfaceCache";
-
+        if (_cacheDir.isEmpty()) {
+            QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
+            _cacheDir = !cachePath.isEmpty() ? cachePath : "interfaceCache";
+        }
         QNetworkDiskCache* cache = new QNetworkDiskCache();
         cache->setMaximumCacheSize(MAXIMUM_CACHE_SIZE);
-        cache->setCacheDirectory(cachePath);
+        cache->setCacheDirectory(_cacheDir);
         networkAccessManager.setCache(cache);
-        qInfo() << "ResourceManager disk cache setup at" << cachePath
+        qInfo() << "ResourceManager disk cache setup at" << _cacheDir
                  << "(size:" << MAXIMUM_CACHE_SIZE / BYTES_PER_GIGABYTES << "GB)";
     }
 }
diff --git a/libraries/networking/src/AssetClient.h b/libraries/networking/src/AssetClient.h
index cab4a4f5b0..2bc694f367 100644
--- a/libraries/networking/src/AssetClient.h
+++ b/libraries/networking/src/AssetClient.h
@@ -49,7 +49,7 @@ using ProgressCallback = std::function<void(qint64 totalReceived, qint64 total)>
 class AssetClient : public QObject, public Dependency {
     Q_OBJECT
 public:
-    AssetClient();
+    AssetClient(const QString& cacheDir="");
 
     Q_INVOKABLE GetMappingRequest* createGetMappingRequest(const AssetPath& path);
     Q_INVOKABLE GetAllMappingsRequest* createGetAllMappingsRequest();
@@ -109,6 +109,8 @@ private:
     std::unordered_map<SharedNodePointer, std::unordered_map<MessageID, GetInfoCallback>> _pendingInfoRequests;
     std::unordered_map<SharedNodePointer, std::unordered_map<MessageID, UploadResultCallback>> _pendingUploads;
 
+    QString _cacheDir;
+
     friend class AssetRequest;
     friend class AssetUpload;
     friend class MappingRequest;
diff --git a/libraries/networking/src/ResourceManager.cpp b/libraries/networking/src/ResourceManager.cpp
index e2c1cf2431..e4357ca507 100644
--- a/libraries/networking/src/ResourceManager.cpp
+++ b/libraries/networking/src/ResourceManager.cpp
@@ -27,7 +27,7 @@
 QThread ResourceManager::_thread;
 ResourceManager::PrefixMap ResourceManager::_prefixMap;
 QMutex ResourceManager::_prefixMapLock;
-
+QString ResourceManager::_cacheDir;
 
 void ResourceManager::setUrlPrefixOverride(const QString& prefix, const QString& replacement) {
     QMutexLocker locker(&_prefixMapLock);
@@ -78,7 +78,7 @@ QUrl ResourceManager::normalizeURL(const QUrl& originalUrl) {
 void ResourceManager::init() {
     _thread.setObjectName("Resource Manager Thread");
 
-    auto assetClient = DependencyManager::set<AssetClient>();
+    auto assetClient = DependencyManager::set<AssetClient>(_cacheDir);
     assetClient->moveToThread(&_thread);
     QObject::connect(&_thread, &QThread::started, assetClient.data(), &AssetClient::init);
 
@@ -164,3 +164,7 @@ bool ResourceManager::resourceExists(const QUrl& url) {
     return false;
 }
 
+void ResourceManager::setCacheDir(const QString& cacheDir) {
+    // TODO: check for existence?  
+    _cacheDir = cacheDir;
+}
diff --git a/libraries/networking/src/ResourceManager.h b/libraries/networking/src/ResourceManager.h
index 41da892701..699573ddd6 100644
--- a/libraries/networking/src/ResourceManager.h
+++ b/libraries/networking/src/ResourceManager.h
@@ -40,6 +40,9 @@ public:
     // to return to the calling thread so that events can still be processed.
     static bool resourceExists(const QUrl& url);
 
+    // adjust where we persist the cache
+    static void setCacheDir(const QString& cacheDir);
+
 private:
     static QThread _thread;
 
@@ -47,6 +50,8 @@ private:
 
     static PrefixMap _prefixMap;
     static QMutex _prefixMapLock;
+
+    static QString _cacheDir;
 };
 
 #endif
diff --git a/libraries/shared/src/PathUtils.cpp b/libraries/shared/src/PathUtils.cpp
index 9bf9d7bdcf..1fe9e2f83d 100644
--- a/libraries/shared/src/PathUtils.cpp
+++ b/libraries/shared/src/PathUtils.cpp
@@ -34,7 +34,18 @@ QString PathUtils::getAppDataPath() {
     return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/";
 }
 
-QString PathUtils::getAppLocalDataPath() {
+QString PathUtils::getAppLocalDataPath(const QString& overridePath /* = "" */) {
+    static QString overriddenPath = "";
+    // set the overridden path if one was passed in
+    if (!overridePath.isEmpty()) {
+        overriddenPath = overridePath;
+    }
+    // return overridden path if set
+    if (!overriddenPath.isEmpty()) {
+        return overriddenPath;
+    }
+
+    // otherwise return standard path
     return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/";
 }
 
diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h
index 14eb81dd9a..42dd09c8b0 100644
--- a/libraries/shared/src/PathUtils.h
+++ b/libraries/shared/src/PathUtils.h
@@ -28,7 +28,7 @@ public:
     static const QString& resourcesPath();
 
     static QString getAppDataPath();
-    static QString getAppLocalDataPath();
+    static QString getAppLocalDataPath(const QString& overridePath = "");
 
     static QString getAppDataFilePath(const QString& filename);
     static QString getAppLocalDataFilePath(const QString& filename);