Add seperate cache path 3111/head
authorShadowNinja <shadowninja@minetest.net>
Mon, 24 Aug 2015 21:00:06 +0000 (17:00 -0400)
committerShadowNinja <shadowninja@minetest.net>
Mon, 7 Dec 2015 18:51:41 +0000 (13:51 -0500)
This is set to the XDG cache path where possible.
It's set to the app's cache path on Android.

src/clientmedia.cpp
src/filesys.cpp
src/filesys.h
src/main.cpp
src/porting.cpp
src/porting.h
src/porting_android.cpp
src/porting_android.h

index ea11ad239ec6210683b0aadd73863bb3aa974f37..bca3f67c28fd721c80fead554074f9c41ac1680d 100644 (file)
@@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 static std::string getMediaCacheDir()
 {
-       return porting::path_user + DIR_DELIM + "cache" + DIR_DELIM + "media";
+       return porting::path_cache + DIR_DELIM + "media";
 }
 
 /*
index 4cefdb807e2580c18a0d559ba0b405414050f34e..5fdc976349acf547559a8aecc041cc8d7e5f2b1e 100644 (file)
@@ -707,5 +707,10 @@ bool safeWriteToFile(const std::string &path, const std::string &content)
        }
 }
 
+bool Rename(const std::string &from, const std::string &to)
+{
+       return rename(from.c_str(), to.c_str()) == 0;
+}
+
 } // namespace fs
 
index cc6f43ec421c9a35d45585c6f702fb433ef763d8..94d0c874dec6611e34c946b4d2ad40161ca06072 100644 (file)
@@ -115,6 +115,8 @@ const char *GetFilenameFromPath(const char *path);
 
 bool safeWriteToFile(const std::string &path, const std::string &content);
 
+bool Rename(const std::string &from, const std::string &to);
+
 } // namespace fs
 
 #endif
index 151ea7148bf4da8f47095d552625d21b2117f5e0..72daaef012a0fe1360e7e51384d7fce41823e703 100644 (file)
@@ -164,7 +164,13 @@ int main(int argc, char *argv[])
        setup_log_params(cmd_args);
 
        porting::signal_handler_init();
+
+#ifdef __ANDROID__
+       porting::initAndroid();
+       porting::initializePathsAndroid();
+#else
        porting::initializePaths();
+#endif
 
        if (!create_userdata_path()) {
                errorstream << "Cannot create user data directory" << std::endl;
@@ -422,9 +428,6 @@ static bool create_userdata_path()
        bool success;
 
 #ifdef __ANDROID__
-       porting::initAndroid();
-
-       porting::setExternalStorageDir(porting::jnienv);
        if (!fs::PathExists(porting::path_user)) {
                success = fs::CreateDir(porting::path_user);
        } else {
@@ -436,9 +439,6 @@ static bool create_userdata_path()
        success = fs::CreateDir(porting::path_user);
 #endif
 
-       infostream << "path_share = " << porting::path_share << std::endl;
-       infostream << "path_user  = " << porting::path_user << std::endl;
-
        return success;
 }
 
index 3e39fc8131ff672df2f6e3bd27a542d15de80bf1..4a72e90fdc26416e8bc909ab2b196481bc1d565c 100644 (file)
@@ -139,6 +139,7 @@ void signal_handler_init(void)
 std::string path_share = "..";
 std::string path_user = "..";
 std::string path_locale = path_share + DIR_DELIM + "locale";
+std::string path_cache = path_user + DIR_DELIM + "cache";
 
 
 std::string getDataPath(const char *subpath)
@@ -463,6 +464,25 @@ bool setSystemPaths()
 
 #endif
 
+void migrateCachePath()
+{
+       const std::string local_cache_path = path_user + DIR_DELIM + "cache";
+
+       // Delete tmp folder if it exists (it only ever contained
+       // a temporary ogg file, which is no longer used).
+       if (fs::PathExists(local_cache_path + DIR_DELIM + "tmp"))
+               fs::RecursiveDelete(local_cache_path + DIR_DELIM + "tmp");
+
+       // Bail if migration impossible
+       if (path_cache == local_cache_path || !fs::PathExists(local_cache_path)
+                       || fs::PathExists(path_cache)) {
+               return;
+       }
+       if (!fs::Rename(local_cache_path, path_cache)) {
+               errorstream << "Failed to migrate local cache path "
+                       "to system path!" << std::endl;
+       }
+}
 
 void initializePaths()
 {
@@ -513,10 +533,27 @@ void initializePaths()
        if (!setSystemPaths())
                errorstream << "Failed to get one or more system-wide path" << std::endl;
 
+       // Initialize path_cache
+       // First try $XDG_CACHE_HOME/PROJECT_NAME
+       const char *cache_dir = getenv("XDG_CACHE_HOME");
+       if (cache_dir) {
+               path_cache = std::string(cache_dir) + DIR_DELIM + PROJECT_NAME;
+       } else {
+               // Then try $HOME/.cache/PROJECT_NAME
+               const char *home_dir = getenv("HOME");
+               if (home_dir) {
+                       path_cache = std::string(home_dir) + DIR_DELIM + ".cache"
+                               + DIR_DELIM + PROJECT_NAME;
+               }
+               // If neither works, leave it at $PATH_USER/cache
+       }
+       // Migrate cache folder to new location if possible
+       migrateCachePath();
 #endif
 
        infostream << "Detected share path: " << path_share << std::endl;
        infostream << "Detected user path: " << path_user << std::endl;
+       infostream << "Detected cache path: " << path_cache << std::endl;
 
        bool found_localedir = false;
 #ifdef STATIC_LOCALEDIR
@@ -542,7 +579,6 @@ void initializePaths()
        if (!found_localedir) {
                errorstream << "Couldn't find a locale directory!" << std::endl;
        }
-
 }
 
 
index 1e89cd04482d5083a1fe694054fd3a0175fa6be8..5da32607cfaa0897c87286670096c24ea6c5631a 100644 (file)
@@ -147,12 +147,23 @@ extern std::string path_user;
 */
 extern std::string path_locale;
 
+/*
+       Path to directory for storing caches.
+*/
+extern std::string path_cache;
+
 /*
        Get full path of stuff in data directory.
        Example: "stone.png" -> "../data/stone.png"
 */
 std::string getDataPath(const char *subpath);
 
+/*
+       Move cache folder from path_user to the
+       system cache location if possible.
+*/
+void migrateCachePath();
+
 /*
        Initialize path_*.
 */
index c7e28cc9a1e57a686e666f64e86bfb1cd2dd8446..72b625d73a0dd4199d9ecd55bc6ba2da5106a427 100644 (file)
@@ -164,29 +164,63 @@ void cleanupAndroid()
        jvm->DetachCurrentThread();
 }
 
-void setExternalStorageDir(JNIEnv* lJNIEnv)
+static std::string javaStringToUTF8(jstring js)
 {
-       // Android: Retrieve ablsolute path to external storage device (sdcard)
-       jclass ClassEnv      = lJNIEnv->FindClass("android/os/Environment");
-       jmethodID MethodDir  =
-                       lJNIEnv->GetStaticMethodID(ClassEnv,
-                                       "getExternalStorageDirectory","()Ljava/io/File;");
-       jobject ObjectFile   = lJNIEnv->CallStaticObjectMethod(ClassEnv, MethodDir);
-       jclass ClassFile     = lJNIEnv->FindClass("java/io/File");
-
-       jmethodID MethodPath =
-                       lJNIEnv->GetMethodID(ClassFile, "getAbsolutePath",
-                                       "()Ljava/lang/String;");
-       jstring StringPath   =
-                       (jstring) lJNIEnv->CallObjectMethod(ObjectFile, MethodPath);
-
-       const char *externalPath = lJNIEnv->GetStringUTFChars(StringPath, NULL);
-       std::string userPath(externalPath);
-       lJNIEnv->ReleaseStringUTFChars(StringPath, externalPath);
-
-       path_storage             = userPath;
-       path_user                = userPath + DIR_DELIM + PROJECT_NAME_C;
-       path_share               = userPath + DIR_DELIM + PROJECT_NAME_C;
+       std::string str;
+       // Get string as a UTF-8 c-string
+       const char *c_str = jnienv->GetStringUTFChars(js, NULL);
+       // Save it
+       str = c_str;
+       // And free the c-string
+       jnienv->ReleaseStringUTFChars(js, c_str);
+       return str;
+}
+
+// Calls static method if obj is NULL
+static std::string getAndroidPath(jclass cls, jobject obj, jclass cls_File,
+               jmethodID mt_getAbsPath, const char *getter)
+{
+       // Get getter method
+       jmethodID mt_getter;
+       if (obj)
+               mt_getter = jnienv->GetMethodID(cls, getter,
+                               "()Ljava/io/File;");
+       else
+               mt_getter = jnienv->GetStaticMethodID(cls, getter,
+                               "()Ljava/io/File;");
+
+       // Call getter
+       jobject ob_file;
+       if (obj)
+               ob_file = jnienv->CallObjectMethod(obj, mt_getter);
+       else
+               ob_file = jnienv->CallStaticObjectMethod(cls, mt_getter);
+
+       // Call getAbsolutePath
+       jstring js_path = (jstring) jnienv->CallObjectMethod(ob_file,
+                       mt_getAbsPath);
+
+       return javaStringToUTF8(js_path);
+}
+
+void initializePathsAndroid()
+{
+       // Get Environment class
+       jclass cls_Env = jnienv->FindClass("android/os/Environment");
+       // Get File class
+       jclass cls_File = jnienv->FindClass("java/io/File");
+       // Get getAbsolutePath method
+       jmethodID mt_getAbsPath = jnienv->GetMethodID(cls_File,
+                               "getAbsolutePath", "()Ljava/lang/String;");
+
+       path_cache   = getAndroidPath(nativeActivity, app_global->activity->clazz,
+                       cls_File, mt_getAbsPath, "getCacheDir");
+       path_storage = getAndroidPath(cls_Env, NULL, cls_File, mt_getAbsPath,
+                       "getExternalStorageDirectory");
+       path_user    = path_storage + DIR_DELIM + PROJECT_NAME_C;
+       path_share   = path_storage + DIR_DELIM + PROJECT_NAME_C;
+
+       migrateCachePath();
 }
 
 void showInputDialog(const std::string& acceptButton, const  std::string& hint,
index bfdadfbff02feb4b9fd22cd014f1fefe17e7e6a7..e4be0740dea53069148755c307725403355e6bdf 100644 (file)
@@ -43,10 +43,10 @@ void initAndroid();
 void cleanupAndroid();
 
 /**
- * set storage dir on external sdcard#
- * @param lJNIEnv environment from android
+ * Initializes path_* variables for Android
+ * @param env Android JNI environment
  */
-void setExternalStorageDir(JNIEnv* lJNIEnv);
+void initializePathsAndroid();
 
 /**
  * use java function to copy media from assets to external storage