diff --git a/programs/disks/CommandList.cpp b/programs/disks/CommandList.cpp index b2361532ceb..c21941c42ca 100644 --- a/programs/disks/CommandList.cpp +++ b/programs/disks/CommandList.cpp @@ -51,7 +51,6 @@ private: static void listRecursive(const DiskWithPath & disk, const std::string & relative_path, bool show_hidden) { - // std::cerr << absolute_path << std::endl; std::vector file_names = disk.listAllFilesByPath(relative_path); std::vector selected_and_sorted_file_names{}; diff --git a/programs/disks/DisksApp.cpp b/programs/disks/DisksApp.cpp index bd4c5293c70..4c1d98ec791 100644 --- a/programs/disks/DisksApp.cpp +++ b/programs/disks/DisksApp.cpp @@ -1,13 +1,9 @@ #include "DisksApp.h" #include #include -#include -#include #include "Common/Exception.h" +#include "Common/filesystemHelpers.h" #include -#include -#include -#include #include "DisksClient.h" #include "ICommand.h" @@ -30,19 +26,20 @@ extern const int BAD_ARGUMENTS; extern const int LOGICAL_ERROR; }; +LineReader::Patterns DisksApp::query_extenders = {"\\"}; +LineReader::Patterns DisksApp::query_delimiters = {""}; +String DisksApp::word_break_characters = " \t\v\f\a\b\r\n"; -CommandPtr DisksApp::getCommandByName(String command) const +CommandPtr DisksApp::getCommandByName(const String & command) const { - auto it = aliases.find(command); - if (it != aliases.end()) - { - command = it->second; - } try { + if (auto it = aliases.find(command); it != aliases.end()) + return command_descriptions.at(it->second); + return command_descriptions.at(command); } - catch (...) + catch (std::out_of_range &) { throw Exception(ErrorCodes::BAD_ARGUMENTS, "The command `{}` is unknown", command); } @@ -75,7 +72,7 @@ std::vector DisksApp::getEmptyCompletion(CommandPtr command_) const std::vector DisksApp::getCompletions(const String & prefix) const { - auto arguments = split(prefix, word_break_characters); + auto arguments = po::split_unix(prefix, word_break_characters); if (arguments.empty()) { return {}; @@ -171,14 +168,14 @@ std::vector DisksApp::getCompletions(const String & prefix) const } } -bool DisksApp::processQueryText(String text) +bool DisksApp::processQueryText(const String & text) { if (exit_strings.find(text) != exit_strings.end()) return false; CommandPtr command; try { - auto arguments = split(text, word_break_characters); + auto arguments = po::split_unix(text, word_break_characters); command = getCommandByName(arguments[0]); arguments.erase(arguments.begin()); command->execute(arguments, *client); @@ -188,7 +185,7 @@ bool DisksApp::processQueryText(String text) int code = getCurrentExceptionCode(); if (code == ErrorCodes::LOGICAL_ERROR) { - throw std::move(err); + throw err; } else if (code == ErrorCodes::BAD_ARGUMENTS) { @@ -272,6 +269,13 @@ void DisksApp::addOptions() #ifdef CLICKHOUSE_CLOUD command_descriptions.emplace("packed-io", makeCommandPackedIO()); #endif + for (const auto & [command_name, command_ptr] : command_descriptions) + { + if (command_name != command_ptr->command_name) + { + throw Exception(ErrorCodes::LOGICAL_ERROR, "Command name inside map doesn't coincide with actual command name"); + } + } } void DisksApp::processOptions() @@ -295,63 +299,35 @@ void DisksApp::printEntryHelpMessage() std::cout << options_description << '\n'; } -size_t DisksApp::getMagicConstant() -{ - size_t magic_constant = 0; - for (const auto & [current_command, _] : command_descriptions) - { - std::string command_string{}; - command_string += command_descriptions[current_command]->command_name; - bool was = false; - for (const auto & [alias_name, alias_command_name] : aliases) - { - if (alias_command_name == current_command) - { - if (was) - command_string += ","; - else - command_string += "("; - command_string += alias_name; - was = true; - } - } - command_string += (was ? ")" : ""); - - magic_constant = std::max(magic_constant, command_string.size()); - } - return magic_constant + 2; -} void DisksApp::printAvailableCommandsHelpMessage() { - size_t magic_constant = getMagicConstant(); - std::cout << "\x1b[1;33mAvailable commands:\x1b[0m\n"; + std::vector> commands_with_aliases_and_descrtiptions{}; + size_t maximal_command_length = 0; for (const auto & [current_command, _] : command_descriptions) { - std::string command_string{}; - command_string += command_descriptions[current_command]->command_name; - bool was = false; + std::string command_string = command_descriptions[current_command]->command_name; + bool need_comma = false; for (const auto & [alias_name, alias_command_name] : aliases) { if (alias_command_name == current_command) { - if (was) + if (std::exchange(need_comma, true)) command_string += ","; else command_string += "("; command_string += alias_name; - was = true; } } - command_string += (was ? ")" : ""); - std::cout << "\x1b[1;32m" << command_string << "\x1b[0m"; - for (size_t i = command_string.size(); i < magic_constant; ++i) - { - std::cout << " "; - } - - std::cout << command_descriptions[current_command]->description << "\n"; + command_string += (need_comma ? ")" : ""); + maximal_command_length = std::max(maximal_command_length, command_string.size()); + commands_with_aliases_and_descrtiptions.push_back({std::move(command_string), command_descriptions[current_command]->command_name}); + } + for (const auto & [command_with_aliases, description] : commands_with_aliases_and_descrtiptions) + { + std::cout << "\x1b[1;32m" << command_with_aliases << "\x1b[0m" + << std::string(maximal_command_length + 2 - command_with_aliases.size(), ' ') << description << "\n"; } } diff --git a/programs/disks/DisksApp.h b/programs/disks/DisksApp.h index fcb4b0b52f5..fad597335f0 100644 --- a/programs/disks/DisksApp.h +++ b/programs/disks/DisksApp.h @@ -25,13 +25,13 @@ public: void processOptions(); - bool processQueryText(String text); + bool processQueryText(const String & text); void init(const std::vector & common_arguments); int main(const std::vector & /*args*/) override; - CommandPtr getCommandByName(String command) const; + CommandPtr getCommandByName(const String & command) const; void initializeHistoryFile(); @@ -45,8 +45,6 @@ public: std::vector getEmptyCompletion(CommandPtr command_) const; - size_t getMagicConstant(); - ~DisksApp() override; private: @@ -57,11 +55,11 @@ private: // Fields responsible for the REPL work String history_file; LineReader::Suggest suggest; - LineReader::Patterns query_extenders = {"\\"}; - LineReader::Patterns query_delimiters = {}; - String word_break_characters{" \t\v\f\a\b\r\n"}; + static LineReader::Patterns query_extenders; + static LineReader::Patterns query_delimiters; + static String word_break_characters; - // General commang line arguments parsing fields + // General command line arguments parsing fields ContextMutablePtr global_context; ProgramOptionsDescription options_description; CommandLineOptions options; @@ -87,5 +85,4 @@ private: std::unique_ptr client{}; }; - } diff --git a/programs/disks/DisksClient.cpp b/programs/disks/DisksClient.cpp index 509892a39a2..1ebfaf40096 100644 --- a/programs/disks/DisksClient.cpp +++ b/programs/disks/DisksClient.cpp @@ -1,17 +1,10 @@ #include "DisksClient.h" #include #include -#include -#include -#include -#include -#include -#include - #include +#include #include -#include namespace ErrorCodes { @@ -22,46 +15,20 @@ extern const int LOGICAL_ERROR; namespace DB { -std::vector split(const String & text, const String & delimiters) +DiskWithPath::DiskWithPath(DiskPtr disk_, std::optional path_) : disk(disk_) { - std::vector arguments; - auto prev = text.begin(); - auto pos = std::find_if(text.begin(), text.end(), [&](char x) { return delimiters.contains(x); }); - while (pos != text.end()) + if (path_.has_value()) { - if (pos > prev) + if (!fs::path{path_.value()}.is_absolute()) { - arguments.push_back({prev, pos}); + throw Exception(ErrorCodes::BAD_ARGUMENTS, "Initializing path {} is not absolute", path_.value()); } - prev = ++pos; - pos = std::find_if(prev, text.end(), [&](char x) { return delimiters.contains(x); }); + path = path_.value(); } - if (pos > prev) + else { - arguments.push_back({prev, text.end()}); + path = String{"/"}; } - return arguments; -} - -DiskWithPath::DiskWithPath(DiskPtr disk_, std::optional path_) - : disk(disk_) - , path( - [&]() - { - if (path_.has_value()) - { - if (!fs::path{path_.value()}.is_absolute()) - { - throw Exception(ErrorCodes::BAD_ARGUMENTS, "Initializing path {} is not absolute", path_.value()); - } - return path_.value(); - } - else - { - return String{"/"}; - } - }()) -{ if (!disk->isDirectory(normalizePathAndGetAsRelative(path))) { throw Exception(ErrorCodes::BAD_ARGUMENTS, "Initializing path {} at disk {} is not a directory", path, disk->getName()); @@ -82,7 +49,7 @@ std::vector DiskWithPath::listAllFilesByPath(const String & any_path) co } } -std::vector DiskWithPath::getAllFilesByPattern(std::string pattern) const +std::vector DiskWithPath::getAllFilesByPattern(const String & pattern) const { auto [path_before, path_after] = [&]() -> std::pair { @@ -149,17 +116,16 @@ String DiskWithPath::validatePathAndGetAsRelative(const String & path) return lexically_normal_path; } -std::string DiskWithPath::normalizePathAndGetAsRelative(const std::string & messyPath) +String DiskWithPath::normalizePathAndGetAsRelative(const String & messyPath) { std::filesystem::path path(messyPath); std::filesystem::path canonical_path = std::filesystem::weakly_canonical(path); - std::string npath = canonical_path.make_preferred().string(); + String npath = canonical_path.make_preferred().string(); return validatePathAndGetAsRelative(npath); } -std::string DiskWithPath::normalizePath(const std::string & messyPath) +String DiskWithPath::normalizePath(const String & path) { - std::filesystem::path path(messyPath); std::filesystem::path canonical_path = std::filesystem::weakly_canonical(path); return canonical_path.make_preferred().string(); } @@ -174,7 +140,7 @@ DisksClient::DisksClient(std::vector>> { begin_disk = disks_with_paths[0].first->getName(); } - bool has_begin_disk = true; + bool has_begin_disk = false; for (auto & [disk, path] : disks_with_paths) { addDisk(disk, path); @@ -265,7 +231,7 @@ std::vector DisksClient::getAllDiskNames() const return answer; } -std::vector DisksClient::getAllFilesByPatternFromAllDisks(std::string pattern) const +std::vector DisksClient::getAllFilesByPatternFromAllDisks(const String & pattern) const { std::vector answer{}; for (const auto & [_, disk] : disks) diff --git a/programs/disks/DisksClient.h b/programs/disks/DisksClient.h index 5c2de7aa529..3320c5f7cef 100644 --- a/programs/disks/DisksClient.h +++ b/programs/disks/DisksClient.h @@ -36,7 +36,7 @@ public: std::vector listAllFilesByPath(const String & any_path) const; - std::vector getAllFilesByPattern(std::string pattern) const; + std::vector getAllFilesByPattern(const String & pattern) const; DiskPtr getDisk() const { return disk; } @@ -74,7 +74,7 @@ public: std::vector getAllDiskNames() const; - std::vector getAllFilesByPatternFromAllDisks(std::string pattern) const; + std::vector getAllFilesByPatternFromAllDisks(const String & pattern) const; private: diff --git a/programs/disks/ICommand.h b/programs/disks/ICommand.h index 1e05aefd28b..d726d50ba13 100644 --- a/programs/disks/ICommand.h +++ b/programs/disks/ICommand.h @@ -4,14 +4,13 @@ #include #include +#include #include -#include #include #include "Common/Exception.h" #include -#include #include #include "DisksApp.h" @@ -46,8 +45,6 @@ public: CommandLineOptions processCommandLineArguments(const Strings & commands); - void exit() { options_parsed = false; } - protected: template static T getValueFromCommandLineOptions(const CommandLineOptions & options, const String & name) @@ -56,7 +53,7 @@ protected: { return options[name].as(); } - catch (...) + catch (boost::bad_any_cast) { throw DB::Exception(ErrorCodes::BAD_ARGUMENTS, "Argument '{}' has wrong type and can't be parsed", name); } @@ -111,9 +108,6 @@ public: protected: PositionalProgramOptionsDescription positional_options_description; - -private: - bool options_parsed{}; }; DB::CommandPtr makeCommandCopy();