From 45f9f0545103b08214ffb3ad2a53e64f45c106c7 Mon Sep 17 00:00:00 2001 From: eidheim Date: Wed, 23 Nov 2016 23:06:55 +0100 Subject: [PATCH] Improved filesystem::(un)escape_argument. Also added filesystem_test. --- src/cmake.cc | 4 ++-- src/debug_lldb.cc | 4 ++-- src/filesystem.cc | 42 ++++++++++++++++++++++++++-------------- src/filesystem.h | 3 +-- src/meson.cc | 4 ++-- src/project.cc | 4 ++-- tests/CMakeLists.txt | 5 +++++ tests/filesystem_test.cc | 36 ++++++++++++++++++++++++++++++++++ 8 files changed, 77 insertions(+), 25 deletions(-) create mode 100644 tests/filesystem_test.cc diff --git a/src/cmake.cc b/src/cmake.cc index 8bb929f..7743f3f 100644 --- a/src/cmake.cc +++ b/src/cmake.cc @@ -52,7 +52,7 @@ bool CMake::update_default_build(const boost::filesystem::path &default_build_pa auto compile_commands_path=default_build_path/"compile_commands.json"; Dialog::Message message("Creating/updating default build"); auto exit_status=Terminal::get().process(Config::get().project.cmake.command+' '+ - filesystem::escape_argument(project_path)+" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON", default_build_path); + filesystem::escape_argument(project_path.string())+" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON", default_build_path); message.hide(); if(exit_status==EXIT_SUCCESS) { #ifdef _WIN32 //Temporary fix to MSYS2's libclang @@ -94,7 +94,7 @@ bool CMake::update_debug_build(const boost::filesystem::path &debug_build_path, Dialog::Message message("Creating/updating debug build"); auto exit_status=Terminal::get().process(Config::get().project.cmake.command+' '+ - filesystem::escape_argument(project_path)+" -DCMAKE_BUILD_TYPE=Debug", debug_build_path); + filesystem::escape_argument(project_path.string())+" -DCMAKE_BUILD_TYPE=Debug", debug_build_path); message.hide(); if(exit_status==EXIT_SUCCESS) return true; diff --git a/src/debug_lldb.cc b/src/debug_lldb.cc index a88ff6c..4159e93 100644 --- a/src/debug_lldb.cc +++ b/src/debug_lldb.cc @@ -60,9 +60,9 @@ void Debug::LLDB::start(const std::string &command, const boost::filesystem::pat if(c==command.size() || (!quote && !double_quote && !symbol && command[c]==' ')) { if(c>0 && start_pos!=std::string::npos) { if(executable.empty()) - executable=filesystem::unescape(command.substr(start_pos, c-start_pos)); + executable=filesystem::unescape_argument(command.substr(start_pos, c-start_pos)); else - arguments.emplace_back(filesystem::unescape(command.substr(start_pos, c-start_pos))); + arguments.emplace_back(filesystem::unescape_argument(command.substr(start_pos, c-start_pos))); start_pos=std::string::npos; } } diff --git a/src/filesystem.cc b/src/filesystem.cc index f15fe0e..5d0f1c3 100644 --- a/src/filesystem.cc +++ b/src/filesystem.cc @@ -138,28 +138,40 @@ bool filesystem::write(const std::string &path, Glib::RefPtr bu std::string filesystem::escape_argument(const std::string &argument) { auto escaped=argument; - size_t pos=0; - while((pos=escaped.find(' ', pos))!=std::string::npos) { - escaped.replace(pos, 1, "\\ "); - pos+=2; + for(size_t pos=0;pos=2) { + if((unescaped[0]=='\'' && unescaped[unescaped.size()-1]=='\'') || + (unescaped[0]=='"' && unescaped[unescaped.size()-1]=='"')) { + char quotation_mark=unescaped[0]; + unescaped=unescaped.substr(1, unescaped.size()-2); + for(size_t pos=1;pos=2) { - if((escaped[0]=='\'' && escaped[escaped.size()-1]=='\'') || - (escaped[0]=='"' && escaped[escaped.size()-1]=='"')) { - escaped=escaped.substr(1, escaped.size()-2); + + for(size_t pos=1;pos text_buffer) { return write(path.string(), text_buffer); } static std::string escape_argument(const std::string &argument); - static std::string escape_argument(const boost::filesystem::path &argument) { return escape_argument(argument.string()); }; - static std::string unescape(const std::string &argument); + static std::string unescape_argument(const std::string &argument); static bool file_in_path(const boost::filesystem::path &file_path, const boost::filesystem::path &path); static boost::filesystem::path find_file_in_path_parents(const std::string &file_name, const boost::filesystem::path &path); diff --git a/src/meson.cc b/src/meson.cc index 2dbd95a..e2776e4 100644 --- a/src/meson.cc +++ b/src/meson.cc @@ -52,7 +52,7 @@ bool Meson::update_default_build(const boost::filesystem::path &default_build_pa Dialog::Message message("Creating/updating default build"); auto exit_status=Terminal::get().process(Config::get().project.meson.command+' '+(compile_commands_exists?"--internal regenerate ":"")+ - filesystem::escape_argument(project_path), default_build_path); + filesystem::escape_argument(project_path.string()), default_build_path); message.hide(); if(exit_status==EXIT_SUCCESS) return true; @@ -78,7 +78,7 @@ bool Meson::update_debug_build(const boost::filesystem::path &debug_build_path, Dialog::Message message("Creating/updating debug build"); auto exit_status=Terminal::get().process(Config::get().project.meson.command+' '+(compile_commands_exists?"--internal regenerate ":"")+ - "--buildtype debug "+filesystem::escape_argument(project_path), debug_build_path); + "--buildtype debug "+filesystem::escape_argument(project_path.string()), debug_build_path); message.hide(); if(exit_status==EXIT_SUCCESS) return true; diff --git a/src/project.cc b/src/project.cc index 6b39b05..5016d00 100644 --- a/src/project.cc +++ b/src/project.cc @@ -224,7 +224,7 @@ std::pair Project::Clang::get_run_arguments() { if(!executable.empty()) arguments=filesystem::escape_argument(executable); else - arguments=filesystem::escape_argument(build->get_default_path()); + arguments=filesystem::escape_argument(build->get_default_path().string()); } return {project_path, arguments}; @@ -370,7 +370,7 @@ std::pair Project::Clang::debug_get_run_arguments() { arguments=filesystem::escape_argument(executable); } else - arguments=filesystem::escape_argument(build->get_debug_path()); + arguments=filesystem::escape_argument(build->get_debug_path().string()); } return {project_path, arguments}; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6b659e9..cd9a390 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -24,6 +24,11 @@ add_executable(compile_commands_test compile_commands_test.cc target_link_libraries(compile_commands_test ${global_libraries}) add_test(compile_commands_test compile_commands_test) +add_executable(filesystem_test filesystem_test.cc + $ $) +target_link_libraries(filesystem_test ${global_libraries}) +add_test(filesystem_test filesystem_test) + add_executable(cmake_build_test cmake_build_test.cc $ $) target_link_libraries(cmake_build_test ${global_libraries}) diff --git a/tests/filesystem_test.cc b/tests/filesystem_test.cc new file mode 100644 index 0000000..02571c6 --- /dev/null +++ b/tests/filesystem_test.cc @@ -0,0 +1,36 @@ +#include "filesystem.h" +#include + +int main() { + { + auto original="test () '\""; + auto escaped=filesystem::escape_argument(original); + g_assert_cmpstr(escaped.c_str(), ==, "test\\ \\(\\)\\ \\'\\\""); + auto unescaped=filesystem::unescape_argument(escaped); + g_assert_cmpstr(unescaped.c_str(), ==, original); + } + { + auto unescaped=filesystem::unescape_argument("'test \\()\"\\''"); + g_assert_cmpstr(unescaped.c_str(), ==, "test \\()\"'"); + } + { + auto unescaped=filesystem::unescape_argument("\"test \\'()\\\"\""); + g_assert_cmpstr(unescaped.c_str(), ==, "test \\'()\""); + } + + auto tests_path=boost::filesystem::canonical(JUCI_TESTS_PATH); + { + g_assert(filesystem::file_in_path(tests_path/"filesystem_test.cc", tests_path)); + g_assert(!filesystem::file_in_path(boost::filesystem::canonical(tests_path/".."/"CMakeLists.txt"), tests_path)); + } + + { + auto license_file=boost::filesystem::canonical(tests_path/".."/"LICENSE"); + g_assert(filesystem::find_file_in_path_parents("LICENSE", tests_path)==license_file); + } + + { + boost::filesystem::path relative_path="filesystem_test.cc"; + g_assert(filesystem::get_relative_path(tests_path/relative_path, tests_path)==relative_path); + } +} \ No newline at end of file