aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--builtin/mainmenu/pkgmgr.lua8
-rw-r--r--src/filesys.cpp24
-rw-r--r--src/filesys.h4
-rw-r--r--src/script/lua_api/l_mainmenu.cpp30
4 files changed, 44 insertions, 22 deletions
diff --git a/builtin/mainmenu/pkgmgr.lua b/builtin/mainmenu/pkgmgr.lua
index d07dc019c..e83a93c91 100644
--- a/builtin/mainmenu/pkgmgr.lua
+++ b/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
diff --git a/src/filesys.cpp b/src/filesys.cpp
index 0972acbf9..44f1c88b3 100644
--- a/src/filesys.cpp
+++ b/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();
diff --git a/src/filesys.h b/src/filesys.h
index 233e56bba..3fa2524c3 100644
--- a/src/filesys.h
+++ b/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
diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp
index 2a6a9c32d..3d80bdafa 100644
--- a/src/script/lua_api/l_mainmenu.cpp
+++ b/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;
}