/* * Copyright (c) 2020, Itamar S. * * SPDX-License-Identifier: BSD-2-Clause */ #include "GitWidget.h" #include "../Dialogs/Git/GitCommitDialog.h" #include "GitFilesModel.h" #include #include #include #include #include #include #include #include #include #include #include namespace HackStudio { GitWidget::GitWidget() { set_layout(); auto& unstaged = add(); unstaged.set_layout(); auto& unstaged_header = unstaged.add(); unstaged_header.set_layout(); auto& refresh_button = unstaged_header.add(); refresh_button.set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/reload.png"sv).release_value_but_fixme_should_propagate_errors()); refresh_button.set_fixed_size(16, 16); refresh_button.set_tooltip("refresh"); refresh_button.on_click = [this](int) { refresh(); }; auto& unstaged_label = unstaged_header.add(); unstaged_label.set_text("Unstaged"); unstaged_header.set_fixed_height(20); m_unstaged_files = unstaged.add( [this](auto const& file) { stage_file(file); }, Gfx::Bitmap::load_from_file("/res/icons/16x16/plus.png"sv).release_value_but_fixme_should_propagate_errors()); m_unstaged_files->on_selection_change = [this] { const auto& index = m_unstaged_files->selection().first(); if (!index.is_valid()) return; const auto& selected = index.data().as_string(); show_diff(selected); }; auto& staged = add(); staged.set_layout(); auto& staged_header = staged.add(); staged_header.set_layout(); auto& commit_button = staged_header.add(); commit_button.set_icon(Gfx::Bitmap::load_from_file("/res/icons/16x16/commit.png"sv).release_value_but_fixme_should_propagate_errors()); commit_button.set_fixed_size(16, 16); commit_button.set_tooltip("commit"); commit_button.on_click = [this](int) { commit(); }; auto& staged_label = staged_header.add(); staged_label.set_text("Staged"); staged_header.set_fixed_height(20); m_staged_files = staged.add( [this](auto const& file) { unstage_file(file); }, Gfx::Bitmap::load_from_file("/res/icons/16x16/minus.png"sv).release_value_but_fixme_should_propagate_errors()); } bool GitWidget::initialize() { auto result = GitRepo::try_to_create(m_repo_root); switch (result.type) { case GitRepo::CreateResult::Type::Success: m_git_repo = result.repo; return true; case GitRepo::CreateResult::Type::GitProgramNotFound: GUI::MessageBox::show(window(), "Please install the Git port"sv, "Error"sv, GUI::MessageBox::Type::Error); return false; case GitRepo::CreateResult::Type::NoGitRepo: { auto decision = GUI::MessageBox::show(window(), "Create git repository?"sv, "Git"sv, GUI::MessageBox::Type::Question, GUI::MessageBox::InputType::YesNo); if (decision != GUI::Dialog::ExecResult::Yes) return false; m_git_repo = GitRepo::initialize_repository(m_repo_root); return true; } default: VERIFY_NOT_REACHED(); } } bool GitWidget::initialize_if_needed() { if (initialized()) return true; return initialize(); } void GitWidget::refresh() { if (!initialize_if_needed()) { dbgln("GitWidget initialization failed"); return; } VERIFY(!m_git_repo.is_null()); m_unstaged_files->set_model(GitFilesModel::create(m_git_repo->unstaged_files())); m_staged_files->set_model(GitFilesModel::create(m_git_repo->staged_files())); } void GitWidget::stage_file(DeprecatedString const& file) { dbgln("staging: {}", file); bool rc = m_git_repo->stage(file); VERIFY(rc); refresh(); } void GitWidget::unstage_file(DeprecatedString const& file) { dbgln("unstaging: {}", file); bool rc = m_git_repo->unstage(file); VERIFY(rc); refresh(); } void GitWidget::commit() { if (m_git_repo.is_null()) { GUI::MessageBox::show(window(), "There is no git repository to commit to!"sv, "Error"sv, GUI::MessageBox::Type::Error); return; } auto dialog = GitCommitDialog::construct(window()); dialog->on_commit = [this](auto& message) { m_git_repo->commit(message); refresh(); }; dialog->exec(); } void GitWidget::set_view_diff_callback(ViewDiffCallback callback) { m_view_diff_callback = move(callback); } void GitWidget::show_diff(DeprecatedString const& file_path) { if (!m_git_repo->is_tracked(file_path)) { auto file = Core::Stream::File::open(file_path, Core::Stream::OpenMode::Read).release_value_but_fixme_should_propagate_errors(); auto content = file->read_until_eof().release_value_but_fixme_should_propagate_errors(); m_view_diff_callback("", Diff::generate_only_additions(content)); return; } auto const& original_content = m_git_repo->original_file_content(file_path); auto const& diff = m_git_repo->unstaged_diff(file_path); VERIFY(original_content.has_value() && diff.has_value()); m_view_diff_callback(original_content.value(), diff.value()); } void GitWidget::change_repo(DeprecatedString const& repo_root) { m_repo_root = repo_root; m_git_repo = nullptr; m_unstaged_files->set_model(nullptr); m_staged_files->set_model(nullptr); } }