Browse Source

Improved filesystem::(un)escape_argument. Also added filesystem_test.

merge-requests/365/head
eidheim 9 years ago
parent
commit
45f9f05451
  1. 4
      src/cmake.cc
  2. 4
      src/debug_lldb.cc
  3. 42
      src/filesystem.cc
  4. 3
      src/filesystem.h
  5. 4
      src/meson.cc
  6. 4
      src/project.cc
  7. 5
      tests/CMakeLists.txt
  8. 36
      tests/filesystem_test.cc

4
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"; auto compile_commands_path=default_build_path/"compile_commands.json";
Dialog::Message message("Creating/updating default build"); Dialog::Message message("Creating/updating default build");
auto exit_status=Terminal::get().process(Config::get().project.cmake.command+' '+ 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(); message.hide();
if(exit_status==EXIT_SUCCESS) { if(exit_status==EXIT_SUCCESS) {
#ifdef _WIN32 //Temporary fix to MSYS2's libclang #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"); Dialog::Message message("Creating/updating debug build");
auto exit_status=Terminal::get().process(Config::get().project.cmake.command+' '+ 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(); message.hide();
if(exit_status==EXIT_SUCCESS) if(exit_status==EXIT_SUCCESS)
return true; return true;

4
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==command.size() || (!quote && !double_quote && !symbol && command[c]==' ')) {
if(c>0 && start_pos!=std::string::npos) { if(c>0 && start_pos!=std::string::npos) {
if(executable.empty()) 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 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; start_pos=std::string::npos;
} }
} }

42
src/filesystem.cc

@ -138,28 +138,40 @@ bool filesystem::write(const std::string &path, Glib::RefPtr<Gtk::TextBuffer> bu
std::string filesystem::escape_argument(const std::string &argument) { std::string filesystem::escape_argument(const std::string &argument) {
auto escaped=argument; auto escaped=argument;
size_t pos=0; for(size_t pos=0;pos<escaped.size();++pos) {
while((pos=escaped.find(' ', pos))!=std::string::npos) { if(escaped[pos]=='\\' || escaped[pos]==' ' || escaped[pos]=='(' || escaped[pos]==')' || escaped[pos]=='\'' || escaped[pos]=='"') {
escaped.replace(pos, 1, "\\ "); escaped.insert(pos, "\\");
pos+=2; ++pos;
}
} }
return escaped; return escaped;
} }
std::string filesystem::unescape(const std::string &argument) { std::string filesystem::unescape_argument(const std::string &argument) {
auto escaped=argument; auto unescaped=argument;
size_t pos=0;
while((pos=escaped.find("\\ ", pos))!=std::string::npos) { if(unescaped.size()>=2) {
escaped.replace(pos, 2, " "); if((unescaped[0]=='\'' && unescaped[unescaped.size()-1]=='\'') ||
pos+=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<unescaped.size();++pos) {
if(unescaped[pos-1]=='\\' && unescaped[pos]==quotation_mark) {
unescaped.erase(pos-1, 1);
--pos;
}
}
return unescaped;
}
} }
if(escaped.size()>=2) {
if((escaped[0]=='\'' && escaped[escaped.size()-1]=='\'') || for(size_t pos=1;pos<unescaped.size();++pos) {
(escaped[0]=='"' && escaped[escaped.size()-1]=='"')) { if(unescaped[pos-1]=='\\' && (unescaped[pos]=='\\' || unescaped[pos]==' ' || unescaped[pos]=='(' || unescaped[pos]==')' || unescaped[pos]=='\'' || unescaped[pos]=='"')) {
escaped=escaped.substr(1, escaped.size()-2); unescaped.erase(pos-1, 1);
--pos;
} }
} }
return escaped; return unescaped;
} }
bool filesystem::file_in_path(const boost::filesystem::path &file_path, const boost::filesystem::path &path) { bool filesystem::file_in_path(const boost::filesystem::path &file_path, const boost::filesystem::path &path) {

3
src/filesystem.h

@ -26,8 +26,7 @@ public:
static bool write(const boost::filesystem::path &path, Glib::RefPtr<Gtk::TextBuffer> text_buffer) { return write(path.string(), text_buffer); } static bool write(const boost::filesystem::path &path, Glib::RefPtr<Gtk::TextBuffer> text_buffer) { return write(path.string(), text_buffer); }
static std::string escape_argument(const std::string &argument); 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_argument(const std::string &argument);
static std::string unescape(const std::string &argument);
static bool file_in_path(const boost::filesystem::path &file_path, const boost::filesystem::path &path); 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); static boost::filesystem::path find_file_in_path_parents(const std::string &file_name, const boost::filesystem::path &path);

4
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"); Dialog::Message message("Creating/updating default build");
auto exit_status=Terminal::get().process(Config::get().project.meson.command+' '+(compile_commands_exists?"--internal regenerate ":"")+ 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(); message.hide();
if(exit_status==EXIT_SUCCESS) if(exit_status==EXIT_SUCCESS)
return true; 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"); Dialog::Message message("Creating/updating debug build");
auto exit_status=Terminal::get().process(Config::get().project.meson.command+' '+(compile_commands_exists?"--internal regenerate ":"")+ 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(); message.hide();
if(exit_status==EXIT_SUCCESS) if(exit_status==EXIT_SUCCESS)
return true; return true;

4
src/project.cc

@ -224,7 +224,7 @@ std::pair<std::string, std::string> Project::Clang::get_run_arguments() {
if(!executable.empty()) if(!executable.empty())
arguments=filesystem::escape_argument(executable); arguments=filesystem::escape_argument(executable);
else else
arguments=filesystem::escape_argument(build->get_default_path()); arguments=filesystem::escape_argument(build->get_default_path().string());
} }
return {project_path, arguments}; return {project_path, arguments};
@ -370,7 +370,7 @@ std::pair<std::string, std::string> Project::Clang::debug_get_run_arguments() {
arguments=filesystem::escape_argument(executable); arguments=filesystem::escape_argument(executable);
} }
else else
arguments=filesystem::escape_argument(build->get_debug_path()); arguments=filesystem::escape_argument(build->get_debug_path().string());
} }
return {project_path, arguments}; return {project_path, arguments};

5
tests/CMakeLists.txt

@ -24,6 +24,11 @@ add_executable(compile_commands_test compile_commands_test.cc
target_link_libraries(compile_commands_test ${global_libraries}) target_link_libraries(compile_commands_test ${global_libraries})
add_test(compile_commands_test compile_commands_test) add_test(compile_commands_test compile_commands_test)
add_executable(filesystem_test filesystem_test.cc
$<TARGET_OBJECTS:project_shared> $<TARGET_OBJECTS:stubs>)
target_link_libraries(filesystem_test ${global_libraries})
add_test(filesystem_test filesystem_test)
add_executable(cmake_build_test cmake_build_test.cc add_executable(cmake_build_test cmake_build_test.cc
$<TARGET_OBJECTS:project_shared> $<TARGET_OBJECTS:stubs>) $<TARGET_OBJECTS:project_shared> $<TARGET_OBJECTS:stubs>)
target_link_libraries(cmake_build_test ${global_libraries}) target_link_libraries(cmake_build_test ${global_libraries})

36
tests/filesystem_test.cc

@ -0,0 +1,36 @@
#include "filesystem.h"
#include <glib.h>
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);
}
}
Loading…
Cancel
Save