Jelajahi Sumber

Move instead of copy during content install if possible

sfan5 2 tahun lalu
induk
melakukan
6de8d77e17
4 mengubah file dengan 44 tambahan dan 22 penghapusan
  1. 2 6
      builtin/mainmenu/pkgmgr.lua
  2. 24 0
      src/filesys.cpp
  3. 4 0
      src/filesys.h
  4. 14 16
      src/script/lua_api/l_mainmenu.cpp

+ 2 - 6
builtin/mainmenu/pkgmgr.lua

@@ -546,11 +546,10 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
 		local from = basefolder and basefolder.path or path
 		if targetpath then
 			core.delete_dir(targetpath)
-			core.create_dir(targetpath)
 		else
 			targetpath = core.get_texturepath() .. DIR_DELIM .. basename
 		end
-		if not core.copy_dir(from, targetpath) then
+		if not core.copy_dir(from, targetpath, false) then
 			return nil,
 				fgettext("Failed to install $1 to $2", basename, targetpath)
 		end
@@ -571,7 +570,6 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
 		-- Get destination name for modpack
 		if targetpath then
 			core.delete_dir(targetpath)
-			core.create_dir(targetpath)
 		else
 			local clean_path = nil
 			if basename ~= nil then
@@ -595,7 +593,6 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
 
 		if targetpath then
 			core.delete_dir(targetpath)
-			core.create_dir(targetpath)
 		else
 			local targetfolder = basename
 			if targetfolder == nil then
@@ -621,14 +618,13 @@ function pkgmgr.install_dir(type, path, basename, targetpath)
 
 		if targetpath then
 			core.delete_dir(targetpath)
-			core.create_dir(targetpath)
 		else
 			targetpath = core.get_gamepath() .. DIR_DELIM .. basename
 		end
 	end
 
 	-- Copy it
-	if not core.copy_dir(basefolder.path, targetpath) then
+	if not core.copy_dir(basefolder.path, targetpath, false) then
 		return nil,
 			fgettext("Failed to install $1 to $2", basename, targetpath)
 	end

+ 24 - 0
src/filesys.cpp

@@ -558,6 +558,30 @@ bool CopyDir(const std::string &source, const std::string &target)
 	return false;
 }
 
+bool MoveDir(const std::string &source, const std::string &target)
+{
+	infostream << "Moving \"" << source << "\" to \"" << target << "\"" << std::endl;
+
+	// If target exists as empty folder delete, otherwise error
+	if (fs::PathExists(target)) {
+		if (rmdir(target.c_str()) != 0) {
+			errorstream << "MoveDir: target \"" << target
+				<< "\" exists as file or non-empty folder" << std::endl;
+			return false;
+		}
+	}
+
+	// Try renaming first which is instant
+	if (fs::Rename(source, target))
+		return true;
+
+	infostream << "MoveDir: rename not possible, will copy instead" << std::endl;
+	bool retval = fs::CopyDir(source, target);
+	if (retval)
+		retval &= fs::RecursiveDelete(source);
+	return retval;
+}
+
 bool PathStartsWith(const std::string &path, const std::string &prefix)
 {
 	size_t pathsize = path.size();

+ 4 - 0
src/filesys.h

@@ -106,6 +106,10 @@ bool CopyFileContents(const std::string &source, const std::string &target);
 // Omits files and subdirectories that start with a period
 bool CopyDir(const std::string &source, const std::string &target);
 
+// Move directory and all subdirectories
+// Behavior with files/subdirs that start with a period is undefined
+bool MoveDir(const std::string &source, const std::string &target);
+
 // Check if one path is prefix of another
 // For example, "/tmp" is a prefix of "/tmp" and "/tmp/file" but not "/tmp2"
 // Ignores case differences and '/' vs. '\\' on Windows

+ 14 - 16
src/script/lua_api/l_mainmenu.cpp

@@ -606,26 +606,24 @@ int ModApiMainMenu::l_copy_dir(lua_State *L)
 	const char *destination	= luaL_checkstring(L, 2);
 
 	bool keep_source = true;
+	if (!lua_isnoneornil(L, 3))
+		keep_source = readParam<bool>(L, 3);
 
-	if ((!lua_isnone(L,3)) &&
-			(!lua_isnil(L,3))) {
-		keep_source = readParam<bool>(L,3);
-	}
-
-	std::string absolute_destination = fs::RemoveRelativePathComponents(destination);
-	std::string absolute_source = fs::RemoveRelativePathComponents(source);
-
-	if ((ModApiMainMenu::mayModifyPath(absolute_destination))) {
-		bool retval = fs::CopyDir(absolute_source,absolute_destination);
-
-		if (retval && (!keep_source)) {
+	std::string abs_destination = fs::RemoveRelativePathComponents(destination);
+	std::string abs_source = fs::RemoveRelativePathComponents(source);
 
-			retval &= fs::RecursiveDelete(absolute_source);
-		}
-		lua_pushboolean(L,retval);
+	if (!ModApiMainMenu::mayModifyPath(abs_destination) ||
+		(!keep_source && !ModApiMainMenu::mayModifyPath(abs_source))) {
+		lua_pushboolean(L, false);
 		return 1;
 	}
-	lua_pushboolean(L,false);
+
+	bool retval;
+	if (keep_source)
+		retval = fs::CopyDir(abs_source, abs_destination);
+	else
+		retval = fs::MoveDir(abs_source, abs_destination);
+	lua_pushboolean(L, retval);
 	return 1;
 }