From 2332ba7cb6ec167b1e61a0b1d09fc0b7b319c309 Mon Sep 17 00:00:00 2001 From: eidheim Date: Thu, 16 Feb 2017 21:27:00 +0100 Subject: [PATCH] Fixes symbolic link issues (see #319) Symbolic paths are now treated like regular paths, but canonical paths are used when looking for already opened files. --- src/cmake.cc | 39 +++++++++++++-------------- src/ctags.cc | 20 +++++--------- src/debug_lldb.cc | 14 +++++----- src/directories.cc | 10 ++++--- src/filesystem.cc | 19 -------------- src/filesystem.h | 3 --- src/git.cc | 2 +- src/juci.cc | 33 +++++++++++------------ src/meson.cc | 33 +++++++++++------------ src/notebook.cc | 10 +++++-- src/project_build.cc | 5 ++-- src/source.cc | 5 ++++ src/source_diff.cc | 10 ++++--- src/source_diff.h | 1 + src/terminal.cc | 11 ++++---- src/window.cc | 55 +++++++++++++-------------------------- tests/cmake_build_test.cc | 8 +++--- tests/filesystem_test.cc | 1 - 18 files changed, 122 insertions(+), 157 deletions(-) diff --git a/src/cmake.cc b/src/cmake.cc index 68a10d2..7773775 100644 --- a/src/cmake.cc +++ b/src/cmake.cc @@ -151,27 +151,24 @@ boost::filesystem::path CMake::get_executable_from_compile_commands(const boost: size_t compile_commands_best_match_size=-1; boost::filesystem::path compile_commands_best_match_executable; for(auto &command: compile_commands.commands) { - boost::system::error_code ec; - auto command_file=boost::filesystem::canonical(command.file, ec); - if(!ec) { - auto values=command.parameter_values("-o"); - if(!values.empty()) { - size_t pos; - values[0].erase(0, 11); - if((pos=values[0].find(".dir"))!=std::string::npos) { - boost::filesystem::path executable=values[0].substr(0, pos); - auto relative_path=filesystem::get_relative_path(command_file, project_path); - if(!relative_path.empty()) { - executable=build_path/relative_path.parent_path()/executable; - if(command_file==file_path) - return executable; - auto command_file_directory=command_file.parent_path(); - if(filesystem::file_in_path(file_path, command_file_directory)) { - auto size=command_file_directory.string().size(); - if(compile_commands_best_match_size==static_cast(-1) || compile_commands_best_match_size(-1) || compile_commands_best_match_size > Ctags::g auto run_path=build->project_path; std::string exclude; if(!run_path.empty()) { - boost::system::error_code ec; - auto default_path=boost::filesystem::canonical(build->get_default_path(), ec); - if(!ec) { - auto path=filesystem::get_relative_path(default_path, build->project_path); - if(!path.empty()) - exclude+=" --exclude="+path.string(); - } - auto debug_path=boost::filesystem::canonical(build->get_debug_path(), ec); - if(!ec) { - auto path=filesystem::get_relative_path(debug_path, build->project_path); - if(!path.empty()) - exclude+=" --exclude="+path.string(); - } + auto relative_default_path=filesystem::get_relative_path(build->get_default_path(), run_path); + if(!relative_default_path.empty()) + exclude+=" --exclude="+relative_default_path.string(); + + auto relative_debug_path=filesystem::get_relative_path(build->get_debug_path(), run_path); + if(!relative_debug_path.empty()) + exclude+=" --exclude="+relative_debug_path.string(); } else { if(!Directories::get().path.empty()) diff --git a/src/debug_lldb.cc b/src/debug_lldb.cc index 9c775dc..e698129 100644 --- a/src/debug_lldb.cc +++ b/src/debug_lldb.cc @@ -210,7 +210,7 @@ void Debug::LLDB::start(const std::string &command, const boost::filesystem::pat auto column=line_entry.GetColumn(); if(column==0) column=1; - stop_callback(filesystem::get_canonical_path(stream.GetData()), line_entry.GetLine(), column); + stop_callback(filesystem::get_normal_path(stream.GetData()), line_entry.GetLine(), column); } else stop_callback("", 0, 0); @@ -346,7 +346,7 @@ std::vector Debug::LLDB::get_backtrace() { auto column=line_entry.GetColumn(); if(column==0) column=1; - backtrace_frame.file_path=filesystem::get_canonical_path(stream.GetData()); + backtrace_frame.file_path=filesystem::get_normal_path(stream.GetData()); backtrace_frame.line_nr=line_entry.GetLine(); backtrace_frame.line_index=column; } @@ -386,7 +386,7 @@ std::vector Debug::LLDB::get_variables() { variable.line_index=1; auto file_spec=declaration.GetFileSpec(); - variable.file_path=filesystem::get_canonical_path(file_spec.GetDirectory()); + variable.file_path=filesystem::get_normal_path(file_spec.GetDirectory()); variable.file_path/=file_spec.GetFilename(); } else { @@ -399,7 +399,7 @@ std::vector Debug::LLDB::get_variables() { variable.line_index=1; auto file_spec=line_entry.GetFileSpec(); - variable.file_path=filesystem::get_canonical_path(file_spec.GetDirectory()); + variable.file_path=filesystem::get_normal_path(file_spec.GetDirectory()); variable.file_path/=file_spec.GetFilename(); } } @@ -443,7 +443,7 @@ std::string Debug::LLDB::get_value(const std::string &variable, const boost::fil if(declaration.IsValid()) { if(declaration.GetLine()==line_nr && (declaration.GetColumn()==0 || declaration.GetColumn()==line_index)) { auto file_spec=declaration.GetFileSpec(); - auto value_decl_path=filesystem::get_canonical_path(file_spec.GetDirectory()); + auto value_decl_path=filesystem::get_normal_path(file_spec.GetDirectory()); value_decl_path/=file_spec.GetFilename(); if(value_decl_path==file_path) { value.GetDescription(stream); @@ -478,7 +478,7 @@ std::string Debug::LLDB::get_return_value(const boost::filesystem::path &file_pa if(line_entry.IsValid()) { lldb::SBStream stream; line_entry.GetFileSpec().GetDescription(stream); - if(filesystem::get_canonical_path(stream.GetData())==file_path && line_entry.GetLine()==line_nr && + if(filesystem::get_normal_path(stream.GetData())==file_path && line_entry.GetLine()==line_nr && (line_entry.GetColumn()==0 || line_entry.GetColumn()==line_index)) { lldb::SBStream stream; thread_return_value.GetDescription(stream); @@ -524,7 +524,7 @@ void Debug::LLDB::remove_breakpoint(const boost::filesystem::path &file_path, in auto line_entry=breakpoint.GetLocationAtIndex(l_index).GetAddress().GetLineEntry(); if(line_entry.GetLine()==static_cast(line_nr_try)) { auto file_spec=line_entry.GetFileSpec(); - auto breakpoint_path=filesystem::get_canonical_path(file_spec.GetDirectory()); + auto breakpoint_path=filesystem::get_normal_path(file_spec.GetDirectory()); breakpoint_path/=file_spec.GetFilename(); if(breakpoint_path==file_path) { if(!target.BreakpointDelete(breakpoint.GetID())) diff --git a/src/directories.cc b/src/directories.cc index 301e5a6..ffa22ca 100644 --- a/src/directories.cc +++ b/src/directories.cc @@ -378,13 +378,16 @@ Directories::~Directories() { } void Directories::open(const boost::filesystem::path &dir_path) { - if(dir_path.empty()) + boost::system::error_code ec; + if(dir_path.empty() || !boost::filesystem::exists(dir_path, ec) || ec) return; tree_store->clear(); + path=filesystem::get_normal_path(dir_path); + //TODO: report that set_title does not handle '_' correctly? - auto title=dir_path.filename().string(); + auto title=path.filename().string(); size_t pos=0; while((pos=title.find('_', pos))!=std::string::npos) { title.replace(pos, 1, "__"); @@ -397,9 +400,8 @@ void Directories::open(const boost::filesystem::path &dir_path) { directory.second.repository->clear_saved_status(); } directories.clear(); - add_or_update_path(dir_path, Gtk::TreeModel::Row(), true); - path=dir_path; + add_or_update_path(path, Gtk::TreeModel::Row(), true); } void Directories::update() { diff --git a/src/filesystem.cc b/src/filesystem.cc index 2b523b1..7d24b03 100644 --- a/src/filesystem.cc +++ b/src/filesystem.cc @@ -192,25 +192,6 @@ boost::filesystem::path filesystem::find_file_in_path_parents(const std::string } } -boost::filesystem::path filesystem::get_canonical_path(const boost::filesystem::path &path) noexcept { - if(path.is_absolute()) { - bool is_canonical=true; - for(auto &str: path) { - if(str==".." || str==".") { - is_canonical=false; - break; - } - } - if(is_canonical) - return path; - } - boost::system::error_code ec; - auto canonical_path=boost::filesystem::canonical(path, ec); - if(ec) - return path; - return canonical_path; -} - boost::filesystem::path filesystem::get_normal_path(const boost::filesystem::path &path) noexcept { boost::filesystem::path normal_path; diff --git a/src/filesystem.h b/src/filesystem.h index dde58a2..72b359d 100644 --- a/src/filesystem.h +++ b/src/filesystem.h @@ -31,9 +31,6 @@ public: 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); - ///Attempts to get canonical path, if not, return the path parameter - static boost::filesystem::path get_canonical_path(const boost::filesystem::path &path) noexcept; - /// Return path with dot, dot-dot and directory separator elements removed static boost::filesystem::path get_normal_path(const boost::filesystem::path &path) noexcept; diff --git a/src/git.cc b/src/git.cc index 550b957..901bca4 100644 --- a/src/git.cc +++ b/src/git.cc @@ -100,7 +100,7 @@ Git::Repository::Repository(const boost::filesystem::path &path) { work_path=get_work_path(); - auto git_path_str=boost::filesystem::canonical(get_path()).string(); + auto git_path_str=get_path().string(); auto git_directory=Glib::wrap(g_file_new_for_path(git_path_str.c_str())); //TODO: report missing constructor in giomm #if GLIBMM_MAJOR_VERSION>2 || (GLIBMM_MAJOR_VERSION==2 && GLIBMM_MINOR_VERSION>=45) monitor=git_directory->monitor_directory(Gio::FileMonitorFlags::FILE_MONITOR_WATCH_MOVES); diff --git a/src/juci.cc b/src/juci.cc index 1e261c6..95f6a8f 100644 --- a/src/juci.cc +++ b/src/juci.cc @@ -14,25 +14,26 @@ int Application::on_command_line(const Glib::RefPtr char **argv = cmd->get_arguments(argc); ctx.parse(argc, argv); if(argc>=2) { + boost::system::error_code current_path_ec; + auto current_path=boost::filesystem::current_path(current_path_ec); + if(current_path_ec) + errors.emplace_back("Error: could not find current path\n"); for(int c=1;c(-1) || best_match_size(-1) || best_match_size &Notebook::get_views() { return source_views; } -void Notebook::open(const boost::filesystem::path &file_path, size_t notebook_index) { +void Notebook::open(const boost::filesystem::path &file_path_, size_t notebook_index) { + auto file_path=filesystem::get_normal_path(file_path_); + if(notebook_index==1 && !split) toggle_split(); + boost::system::error_code ec; + auto canonical_file_path=boost::filesystem::canonical(file_path, ec); + if(ec) + canonical_file_path=file_path; for(size_t c=0;cfile_path) { + if(canonical_file_path==source_views[c]->canonical_file_path) { auto notebook_page=get_notebook_page(c); notebooks[notebook_page.first].set_current_page(notebook_page.second); focus_view(source_views[c]); diff --git a/src/project_build.cc b/src/project_build.cc index afc04a1..45de37f 100644 --- a/src/project_build.cc +++ b/src/project_build.cc @@ -1,5 +1,6 @@ #include "project_build.h" #include "config.h" +#include "filesystem.h" std::unique_ptr Project::Build::create(const boost::filesystem::path &path) { auto search_path=boost::filesystem::is_directory(path)?path:path.parent_path(); @@ -47,7 +48,7 @@ boost::filesystem::path Project::Build::get_default_path() { if(default_build_path.is_relative()) default_build_path=project_path/default_build_path; - return default_build_path; + return filesystem::get_normal_path(default_build_path); } boost::filesystem::path Project::Build::get_debug_path() { @@ -81,7 +82,7 @@ boost::filesystem::path Project::Build::get_debug_path() { if(debug_build_path.is_relative()) debug_build_path=project_path/debug_build_path; - return debug_build_path; + return filesystem::get_normal_path(debug_build_path); } Project::CMakeBuild::CMakeBuild(const boost::filesystem::path &path) : Project::Build(), cmake(path) { diff --git a/src/source.cc b/src/source.cc index b5a8951..fd2e52b 100644 --- a/src/source.cc +++ b/src/source.cc @@ -425,6 +425,11 @@ void Source::View::rename(const boost::filesystem::path &path) { { std::unique_lock lock(file_path_mutex); file_path=path; + + boost::system::error_code ec; + canonical_file_path=boost::filesystem::canonical(file_path, ec); + if(ec) + canonical_file_path=file_path; } if(update_status_file_path) update_status_file_path(this); diff --git a/src/source_diff.cc b/src/source_diff.cc index 848ae98..0cbd637 100644 --- a/src/source_diff.cc +++ b/src/source_diff.cc @@ -49,13 +49,17 @@ void Source::DiffView::Renderer::draw_vfunc(const Cairo::RefPtr } Source::DiffView::DiffView(const boost::filesystem::path &file_path) : Gsv::View(), file_path(file_path), renderer(new Renderer()) { + boost::system::error_code ec; + canonical_file_path=boost::filesystem::canonical(file_path, ec); + if(ec) + canonical_file_path=file_path; + renderer->tag_added=get_buffer()->create_tag("git_added"); renderer->tag_modified=get_buffer()->create_tag("git_modified"); renderer->tag_removed=get_buffer()->create_tag("git_removed"); renderer->tag_removed_below=get_buffer()->create_tag(); renderer->tag_removed_above=get_buffer()->create_tag(); - boost::system::error_code ec; last_write_time=boost::filesystem::last_write_time(file_path, ec); if(ec) last_write_time=static_cast(-1); @@ -346,11 +350,11 @@ std::string Source::DiffView::git_get_diff_details() { ///Return repository diff instance. Throws exception on error std::unique_ptr Source::DiffView::get_diff() { - auto work_path=boost::filesystem::canonical(repository->get_work_path()); + auto work_path=filesystem::get_normal_path(repository->get_work_path()); boost::filesystem::path relative_path; { std::unique_lock lock(file_path_mutex); - relative_path=filesystem::get_relative_path(file_path, work_path); + relative_path=filesystem::get_relative_path(canonical_file_path, work_path); if(relative_path.empty()) throw std::runtime_error("not a relative path"); } diff --git a/src/source_diff.h b/src/source_diff.h index 63df609..ab6034f 100644 --- a/src/source_diff.h +++ b/src/source_diff.h @@ -34,6 +34,7 @@ namespace Source { ~DiffView(); boost::filesystem::path file_path; + boost::filesystem::path canonical_file_path; protected: std::mutex file_path_mutex; std::time_t last_write_time; diff --git a/src/terminal.cc b/src/terminal.cc index ffd4596..62365a1 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -357,19 +357,18 @@ bool Terminal::on_button_press_event(GdkEventButton* button_event) { if(std::regex_match(path_str, sm, link_regex)) { auto path_str=sm[1].str()+sm[2].str(); auto path=boost::filesystem::path(path_str); - boost::system::error_code ec; if(path.is_relative()) { if(Project::current) { - path=boost::filesystem::canonical(Project::current->build->get_default_path()/path_str, ec); - if(ec) - path=boost::filesystem::canonical(Project::current->build->get_debug_path()/path_str, ec); + path=Project::current->build->get_default_path()/path_str; + if(!boost::filesystem::is_regular_file(path)) + path=Project::current->build->get_debug_path()/path_str; } else return Gtk::TextView::on_button_press_event(button_event); } else - path=boost::filesystem::canonical(path_str, ec); - if(!ec && boost::filesystem::is_regular_file(path)) { + path=path_str; + if(boost::filesystem::is_regular_file(path)) { Notebook::get().open(path); if(auto view=Notebook::get().get_current_view()) { try { diff --git a/src/window.cc b/src/window.cc index a73ae40..9869409 100644 --- a/src/window.cc +++ b/src/window.cc @@ -601,8 +601,14 @@ void Window::set_menu_actions() { ctags_path=view->file_path.parent_path(); else if(!Directories::get().path.empty()) ctags_path=Directories::get().path; - else - ctags_path=boost::filesystem::current_path(); + else { + boost::system::error_code ec; + ctags_path=boost::filesystem::current_path(ec); + if(ec) { + Terminal::get().print("Error: could not find current path\n", true); + return; + } + } auto pair=Ctags::get_result(ctags_path); auto path=std::move(pair.first); @@ -636,12 +642,7 @@ void Window::set_menu_actions() { return; SelectionDialog::get()->on_select=[this, rows, path](const std::string &selected, bool hide_window) { auto offset=rows->at(selected); - boost::filesystem::path declaration_file; - boost::system::error_code ec; - declaration_file=boost::filesystem::canonical(path/offset.file_path, ec); - if(ec) - return; - Notebook::get().open(declaration_file); + Notebook::get().open(path/offset.file_path); auto view=Notebook::get().get_current_view(); view->place_cursor_at_line_index(offset.line, offset.index); view->scroll_to_cursor_delayed(view, true, false); @@ -665,11 +666,7 @@ void Window::set_menu_actions() { auto documentation_template=view->get_documentation_template(); auto offset=std::get<0>(documentation_template); if(offset) { - boost::system::error_code ec; - auto canonical_path=boost::filesystem::canonical(offset.file_path, ec); - if(ec) - return; - Notebook::get().open(canonical_path); + Notebook::get().open(offset.file_path); auto view=Notebook::get().get_current_view(); auto iter=view->get_buffer()->get_iter_at_line_index(offset.line, offset.index); view->get_buffer()->insert(iter, std::get<1>(documentation_template)); @@ -727,12 +724,7 @@ void Window::set_menu_actions() { if(view->get_declaration_location) { auto location=view->get_declaration_location(); if(location) { - boost::filesystem::path declaration_file; - boost::system::error_code ec; - declaration_file=boost::filesystem::canonical(location.file_path, ec); - if(ec) - return; - Notebook::get().open(declaration_file); + Notebook::get().open(location.file_path); auto view=Notebook::get().get_current_view(); auto line=static_cast(location.line); auto index=static_cast(location.index); @@ -758,18 +750,12 @@ void Window::set_menu_actions() { project_path=view->file_path.parent_path(); } for(auto &location: locations) { - boost::filesystem::path implementation_path; - boost::system::error_code ec; - implementation_path=boost::filesystem::canonical(location.file_path, ec); - if(!ec) { - location.file_path=implementation_path; - auto path=filesystem::get_relative_path(location.file_path, project_path); - if(path.empty()) - path=location.file_path.filename(); - auto row=path.string()+":"+std::to_string(location.line+1); - (*rows)[row]=location; - SelectionDialog::get()->add_row(row); - } + auto path=filesystem::get_relative_path(filesystem::get_normal_path(location.file_path), project_path); + if(path.empty()) + path=location.file_path.filename(); + auto row=path.string()+":"+std::to_string(location.line+1); + (*rows)[row]=location; + SelectionDialog::get()->add_row(row); } if(rows->size()==0) @@ -832,12 +818,7 @@ void Window::set_menu_actions() { return; SelectionDialog::get()->on_select=[this, rows](const std::string &selected, bool hide_window) { auto offset=rows->at(selected); - boost::filesystem::path declaration_file; - boost::system::error_code ec; - declaration_file=boost::filesystem::canonical(offset.file_path, ec); - if(ec) - return; - Notebook::get().open(declaration_file); + Notebook::get().open(offset.file_path); auto view=Notebook::get().get_current_view(); view->place_cursor_at_line_index(offset.line, offset.index); view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5); diff --git a/tests/cmake_build_test.cc b/tests/cmake_build_test.cc index eec0908..dd6a94f 100644 --- a/tests/cmake_build_test.cc +++ b/tests/cmake_build_test.cc @@ -45,17 +45,17 @@ int main() { g_assert(build->project_path==project_path); Config::get().project.default_build_path="./build"; - g_assert(build->get_default_path()==project_path/"./build"); + g_assert(build->get_default_path()==project_path/"build"); Config::get().project.debug_build_path="/debug"; - g_assert(build->get_debug_path()==project_path/"./build/debug"); + g_assert(build->get_debug_path()==project_path/"build/debug"); auto project_path_filename=project_path.filename(); Config::get().project.debug_build_path="../debug_"; - g_assert(build->get_debug_path()==project_path/("../debug_"+project_path_filename.string())); + g_assert(build->get_debug_path()==project_path.parent_path()/("debug_"+project_path_filename.string())); Config::get().project.default_build_path="../build_"; - g_assert(build->get_default_path()==project_path/("../build_"+project_path_filename.string())); + g_assert(build->get_default_path()==project_path.parent_path()/("build_"+project_path_filename.string())); } { auto project_path=tests_path/"source_clang_test_files"; diff --git a/tests/filesystem_test.cc b/tests/filesystem_test.cc index 91571bc..b36d74d 100644 --- a/tests/filesystem_test.cc +++ b/tests/filesystem_test.cc @@ -1,6 +1,5 @@ #include "filesystem.h" #include -#include int main() { {