Move instead of copy during content install if possible

This commit is contained in:
sfan5 2021-09-19 18:16:53 +02:00
parent 2b5075f0e2
commit 6de8d77e17
4 changed files with 44 additions and 22 deletions

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

@ -558,6 +558,30 @@ bool CopyDir(const std::string &source, const std::string &target)
return false; 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) bool PathStartsWith(const std::string &path, const std::string &prefix)
{ {
size_t pathsize = path.size(); size_t pathsize = path.size();

@ -106,6 +106,10 @@ bool CopyFileContents(const std::string &source, const std::string &target);
// Omits files and subdirectories that start with a period // Omits files and subdirectories that start with a period
bool CopyDir(const std::string &source, const std::string &target); 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 // Check if one path is prefix of another
// For example, "/tmp" is a prefix of "/tmp" and "/tmp/file" but not "/tmp2" // For example, "/tmp" is a prefix of "/tmp" and "/tmp/file" but not "/tmp2"
// Ignores case differences and '/' vs. '\\' on Windows // Ignores case differences and '/' vs. '\\' on Windows

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