Browse Source

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.
merge-requests/365/head
eidheim 9 years ago
parent
commit
2332ba7cb6
  1. 5
      src/cmake.cc
  2. 20
      src/ctags.cc
  3. 14
      src/debug_lldb.cc
  4. 10
      src/directories.cc
  5. 19
      src/filesystem.cc
  6. 3
      src/filesystem.h
  7. 2
      src/git.cc
  8. 33
      src/juci.cc
  9. 5
      src/meson.cc
  10. 10
      src/notebook.cc
  11. 5
      src/project_build.cc
  12. 5
      src/source.cc
  13. 10
      src/source_diff.cc
  14. 1
      src/source_diff.h
  15. 11
      src/terminal.cc
  16. 45
      src/window.cc
  17. 8
      tests/cmake_build_test.cc
  18. 1
      tests/filesystem_test.cc

5
src/cmake.cc

@ -151,9 +151,7 @@ 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 command_file=filesystem::get_normal_path(command.file);
auto values=command.parameter_values("-o");
if(!values.empty()) {
size_t pos;
@ -177,7 +175,6 @@ boost::filesystem::path CMake::get_executable_from_compile_commands(const boost:
}
}
}
}
return compile_commands_best_match_executable;
}

20
src/ctags.cc

@ -14,19 +14,13 @@ std::pair<boost::filesystem::path, std::unique_ptr<std::stringstream> > 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())

14
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::Frame> 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::Variable> 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::Variable> 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<uint32_t>(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()))

10
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() {

19
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;

3
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;

2
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);

33
src/juci.cc

@ -14,25 +14,26 @@ int Application::on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine>
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<argc;c++) {
boost::filesystem::path p(argv[c]);
if(boost::filesystem::exists(p)) {
p=boost::filesystem::canonical(p);
if(boost::filesystem::is_regular_file(p))
files.emplace_back(p, 0);
else if(boost::filesystem::is_directory(p))
directories.emplace_back(p);
}
else { //Open new file if parent path exists
auto parent_p=p.parent_path();
boost::system::error_code ec;
auto new_p=boost::filesystem::canonical(parent_p, ec);
if(!ec && boost::filesystem::is_directory(new_p)) {
new_p/=p.filename();
files.emplace_back(new_p, 0);
boost::filesystem::path path(argv[c]);
if(path.is_relative() && !current_path_ec)
path=current_path/path;
if(boost::filesystem::exists(path)) {
if(boost::filesystem::is_regular_file(path))
files.emplace_back(path, 0);
else if(boost::filesystem::is_directory(path))
directories.emplace_back(path);
}
//Open new file if parent path exists
else {
if(path.is_absolute() && boost::filesystem::is_directory(path.parent_path()))
files.emplace_back(path, 0);
else
errors.emplace_back("Error: folder path "+parent_p.string()+" does not exist.\n");
errors.emplace_back("Error: could not create "+path.string()+".\n");
}
}
}

5
src/meson.cc

@ -91,9 +91,7 @@ boost::filesystem::path Meson::get_executable(const boost::filesystem::path &bui
size_t best_match_size=-1;
boost::filesystem::path 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 command_file=filesystem::get_normal_path(command.file);
auto values=command.parameter_values("-o");
if(!values.empty()) {
size_t pos;
@ -114,7 +112,6 @@ boost::filesystem::path Meson::get_executable(const boost::filesystem::path &bui
}
}
}
}
return best_match_executable;
}

10
src/notebook.cc

@ -129,12 +129,18 @@ std::vector<Source::View*> &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;c<size();c++) {
if(file_path==source_views[c]->file_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]);

5
src/project_build.cc

@ -1,5 +1,6 @@
#include "project_build.h"
#include "config.h"
#include "filesystem.h"
std::unique_ptr<Project::Build> 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) {

5
src/source.cc

@ -425,6 +425,11 @@ void Source::View::rename(const boost::filesystem::path &path) {
{
std::unique_lock<std::mutex> 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);

10
src/source_diff.cc

@ -49,13 +49,17 @@ void Source::DiffView::Renderer::draw_vfunc(const Cairo::RefPtr<Cairo::Context>
}
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<std::time_t>(-1);
@ -346,11 +350,11 @@ std::string Source::DiffView::git_get_diff_details() {
///Return repository diff instance. Throws exception on error
std::unique_ptr<Git::Repository::Diff> 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<std::mutex> 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");
}

1
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;

11
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 {

45
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<int>(location.line);
auto index=static_cast<int>(location.index);
@ -758,19 +750,13 @@ 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);
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)
return;
@ -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);

8
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="<default_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_<project_directory_name>";
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_<project_directory_name>";
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";

1
tests/filesystem_test.cc

@ -1,6 +1,5 @@
#include "filesystem.h"
#include <glib.h>
#include <iostream>
int main() {
{

Loading…
Cancel
Save