From 56fc949646ee70f30584e8ffbbff77f8b89fa257 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20De=20Canni=C3=A8re?= Date: Wed, 28 Apr 2021 16:01:14 +0200 Subject: [PATCH] HackStudio: Detection of externally deleted files HackStudio can now detect that files that have been opened in it were deleted. When this occurs, it will update the list of open files and reasign a file to the editors that showed the deleted file before the deletion. The new file is either another file that was opened or the default editor is no other open file is available Closes SerenityOS#6632 --- .../DevTools/HackStudio/HackStudioWidget.cpp | 46 +++++++++++++++++++ .../DevTools/HackStudio/HackStudioWidget.h | 5 +- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/Userland/DevTools/HackStudio/HackStudioWidget.cpp b/Userland/DevTools/HackStudio/HackStudioWidget.cpp index 0fafe27a98..c79b7979fc 100644 --- a/Userland/DevTools/HackStudio/HackStudioWidget.cpp +++ b/Userland/DevTools/HackStudio/HackStudioWidget.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -231,6 +233,20 @@ bool HackStudioWidget::open_file(const String& full_filename) new_project_file = m_project->get_file(filename); m_open_files.set(filename, *new_project_file); m_open_files_vector.append(filename); + auto watcher_or_error = Core::FileWatcher::watch(filename); + if (!watcher_or_error.is_error()) { + auto& watcher = watcher_or_error.value(); + watcher->on_change = [this, filename]() { + struct stat st; + if (lstat(filename.characters(), &st) < 0) { + if (errno == ENOENT) { + handle_external_file_deletion(filename); + } + } + }; + m_file_watchers.set(filename, watcher_or_error.release_value()); + } + m_open_files_view->model()->update(); } @@ -1074,6 +1090,36 @@ void HackStudioWidget::initialize_menubar(GUI::Menubar& menubar) create_help_menubar(menubar); } +void HackStudioWidget::handle_external_file_deletion(const String& filepath) +{ + m_open_files.remove(filepath); + m_open_files_vector.remove_all_matching( + [&filepath](const String& element) { return element == filepath; }); + + for (auto& editor_wrapper : m_all_editor_wrappers) { + Editor& editor = editor_wrapper.editor(); + String editor_file_path = editor.code_document().file_path(); + String relative_editor_file_path = LexicalPath::relative_path(editor_file_path, project().root_path()); + + if (relative_editor_file_path == filepath) { + if (m_open_files_vector.is_empty()) { + editor.set_document(CodeDocument::create()); + editor_wrapper.filename_label().set_text(String { "Undefined" }); + m_currently_open_file = ""; + } else { + auto& first_path = m_open_files_vector[0]; + auto& document = m_open_files.get(first_path).value()->code_document(); + editor.set_document(document); + editor_wrapper.filename_label().set_text(first_path); + m_currently_open_file = first_path; + } + } + } + + m_file_watchers.remove(filepath); + m_open_files_view->model()->update(); +} + HackStudioWidget::~HackStudioWidget() { if (!m_debugger_thread.is_null()) { diff --git a/Userland/DevTools/HackStudio/HackStudioWidget.h b/Userland/DevTools/HackStudio/HackStudioWidget.h index 9cf5e8b6d6..312d138bf3 100644 --- a/Userland/DevTools/HackStudio/HackStudioWidget.h +++ b/Userland/DevTools/HackStudio/HackStudioWidget.h @@ -93,6 +93,8 @@ private: void reveal_action_tab(GUI::Widget&); void initialize_debugger(); + void handle_external_file_deletion(const String& filepath); + void create_open_files_view(GUI::Widget& parent); void create_form_editor(GUI::Widget& parent); void create_toolbar(GUI::Widget& parent); @@ -118,7 +120,8 @@ private: String m_currently_open_file; HashMap> m_open_files; - Vector m_open_files_vector; // NOTE: This contains the keys from m_open_files + HashMap> m_file_watchers; + Vector m_open_files_vector; // NOTE: This contains the keys from m_open_files and m_file_watchers OwnPtr m_project;