Change wrong implementations of copy and move

This commit is contained in:
divanik 2024-07-01 11:11:16 +00:00
parent 90601e0a1d
commit bb0b93f77d
6 changed files with 126 additions and 12 deletions

View File

@ -1,4 +1,5 @@
#include <Interpreters/Context.h>
#include "Common/Exception.h"
#include <Common/TerminalSize.h>
#include "DisksClient.h"
#include "ICommand.h"
@ -17,7 +18,8 @@ public:
"disk-from", po::value<String>(), "disk from which we copy is executed (default value is a current disk)")(
"disk-to", po::value<String>(), "disk to which copy is executed (default value is a current disk)")(
"path-from", po::value<String>(), "path from which copy is executed (mandatory, positional)")(
"path-to", po::value<String>(), "path to which copy is executed (mandatory, positional)");
"path-to", po::value<String>(), "path to which copy is executed (mandatory, positional)")(
"recursive", "recursively copy the directory");
positional_options_description.add("path-from", 1);
positional_options_description.add("path-to", 1);
}
@ -28,9 +30,55 @@ public:
auto disk_to = getDiskWithPath(client, options, "disk-to");
String path_from = disk_from.getRelativeFromRoot(getValueFromCommandLineOptionsThrow<String>(options, "path-from"));
String path_to = disk_to.getRelativeFromRoot(getValueFromCommandLineOptionsThrow<String>(options, "path-to"));
bool recursive = options.count("recursive");
disk_from.getDisk()->copyDirectoryContent(
path_from, disk_to.getDisk(), path_to, /* read_settings= */ {}, /* write_settings= */ {}, /* cancellation_hook= */ {});
if (!disk_from.getDisk()->exists(path_from))
{
throw Exception(ErrorCodes::BAD_ARGUMENTS, "cannot stat '{}': No such file or directory", path_from);
}
else if (disk_from.getDisk()->isFile(path_from))
{
auto target_location = getTargetLocation(path_from, disk_to, path_to);
if (!disk_to.getDisk()->exists(target_location) || disk_to.getDisk()->isFile(target_location))
{
disk_from.getDisk()->copyFile(
path_from,
*disk_to.getDisk(),
target_location,
/* read_settings= */ {},
/* write_settings= */ {},
/* cancellation_hook= */ {});
}
else
{
throw Exception(
ErrorCodes::BAD_ARGUMENTS, "cannot overwrite directory {} with non-directory {}", target_location, path_from);
}
}
else if (disk_from.getDisk()->isDirectory(path_from))
{
if (!recursive)
{
throw Exception(ErrorCodes::BAD_ARGUMENTS, "--recursive not specified; omitting directory {}", path_from);
}
auto target_location = getTargetLocation(path_from, disk_to, path_to);
if (disk_to.getDisk()->isFile(target_location))
{
throw Exception(ErrorCodes::BAD_ARGUMENTS, "cannot overwrite non-directory {} with directory {}", path_to, target_location);
}
else if (!disk_to.getDisk()->exists(target_location))
{
disk_to.getDisk()->createDirectory(target_location);
}
disk_from.getDisk()->copyDirectoryContent(
path_from,
disk_to.getDisk(),
target_location,
/* read_settings= */ {},
/* write_settings= */ {},
/* cancellation_hook= */ {});
}
}
};

View File

@ -13,14 +13,14 @@ public:
{
command_name = "mkdir";
description = "Creates a directory";
options_description.add_options()("recursive", "recursively create directories")(
"path", po::value<String>(), "the path of listing (mandatory, positional)");
options_description.add_options()("parents", "recursively create directories")(
"path", po::value<String>(), "the path on which directory should be created (mandatory, positional)");
positional_options_description.add("path", 1);
}
void executeImpl(const CommandLineOptions & options, DisksClient & client) override
{
bool recursive = options.count("recursive");
bool recursive = options.count("parents");
auto disk = client.getCurrentDiskWithPath();
String path = disk.getRelativeFromRoot(getValueFromCommandLineOptionsThrow<String>(options, "path"));

View File

@ -25,9 +25,38 @@ public:
String path_to = disk.getRelativeFromRoot(getValueFromCommandLineOptionsThrow<String>(options, "path-to"));
if (disk.getDisk()->isFile(path_from))
{
disk.getDisk()->moveFile(path_from, path_to);
else
disk.getDisk()->moveDirectory(path_from, path_to);
}
else if (disk.getDisk()->isDirectory(path_from))
{
auto target_location = getTargetLocation(path_from, disk, path_to);
if (!disk.getDisk()->exists(target_location))
{
disk.getDisk()->createDirectory(target_location);
disk.getDisk()->moveDirectory(path_from, target_location);
}
else
{
if (disk.getDisk()->isFile(target_location))
{
throw Exception(
ErrorCodes::BAD_ARGUMENTS, "cannot overwrite non-directory '{}' with directory '{}'", target_location, path_from);
}
if (!disk.getDisk()->isDirectoryEmpty(target_location))
{
throw Exception(ErrorCodes::BAD_ARGUMENTS, "cannot move '{}' to '{}': Directory not empty", path_from, target_location);
}
else
{
disk.getDisk()->moveDirectory(path_from, target_location);
}
}
}
else if (!disk.getDisk()->exists(path_from))
{
throw Exception(ErrorCodes::BAD_ARGUMENTS, "cannot stat '{}': No such file or directory", path_from);
}
}
};

View File

@ -1,4 +1,5 @@
#include <Interpreters/Context.h>
#include "Common/Exception.h"
#include "ICommand.h"
namespace DB
@ -10,8 +11,9 @@ public:
CommandRemove()
{
command_name = "remove";
description = "Remove file or directory with all children. Throws exception if file doesn't exists";
options_description.add_options()("path", po::value<String>(), "path from which we copy (mandatory, positional)");
description = "Remove file or directory. Throws exception if file doesn't exists";
options_description.add_options()("path", po::value<String>(), "path from which we copy (mandatory, positional)")(
"recursive", "recursively removes the directory (required to remove a directory)");
positional_options_description.add("path", 1);
}
@ -19,7 +21,26 @@ public:
{
auto disk = client.getCurrentDiskWithPath();
const String & path = disk.getRelativeFromRoot(getValueFromCommandLineOptionsThrow<String>(options, "path"));
disk.getDisk()->removeRecursive(path);
bool recursive = options.count("recursive");
if (!disk.getDisk()->exists(path))
{
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Path {} on disk {} doesn't exist", path, disk.getDisk()->getName());
}
else if (disk.getDisk()->isDirectory(path))
{
if (!recursive)
{
throw Exception(ErrorCodes::BAD_ARGUMENTS, "cannot remove '{}': Is a directory", path);
}
else
{
disk.getDisk()->removeRecursive(path);
}
}
else
{
disk.getDisk()->removeFileIfExists(path);
}
}
};

View File

@ -20,7 +20,7 @@ DiskWithPath::DiskWithPath(DiskPtr disk_, std::optional<String> path_) : disk(di
{
if (!fs::path{path_.value()}.is_absolute())
{
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Initializing path {} is not absolute", path_.value());
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Initializing path {} is not absolute", path_.value());
}
path = path_.value();
}

View File

@ -100,6 +100,22 @@ protected:
DiskWithPath & getDiskWithPath(DisksClient & client, const CommandLineOptions & options, const String & name);
String getTargetLocation(const String & path_from, DiskWithPath & disk_to, const String & path_to)
{
if (!disk_to.getDisk()->isDirectory(path_to))
{
return path_to;
}
String copied_path_from = path_from;
if (copied_path_from.ends_with('/'))
{
copied_path_from.pop_back();
}
String plain_filename = fs::path(copied_path_from).filename();
return fs::path{path_to} / plain_filename;
}
public:
String command_name;