From 24532d3f784616a0ef122e2084759ff16a484ed0 Mon Sep 17 00:00:00 2001 From: Johan Mabille Date: Fri, 6 Feb 2026 18:15:38 +0100 Subject: [PATCH] Implemented git rm --- src/subcommand/rm_subcommand.cpp | 49 ++++++++++++++++++++++++++++++++ src/subcommand/rm_subcommand.hpp | 21 ++++++++++++++ src/wrapper/index_wrapper.cpp | 15 ++++++++++ src/wrapper/index_wrapper.hpp | 2 ++ 4 files changed, 87 insertions(+) create mode 100644 src/subcommand/rm_subcommand.cpp create mode 100644 src/subcommand/rm_subcommand.hpp diff --git a/src/subcommand/rm_subcommand.cpp b/src/subcommand/rm_subcommand.cpp new file mode 100644 index 0000000..d049c18 --- /dev/null +++ b/src/subcommand/rm_subcommand.cpp @@ -0,0 +1,49 @@ +#include +#include "rm_subcommand.hpp" +#include "../utils/common.hpp" +#include "../utils/git_exception.hpp" +#include "../wrapper/index_wrapper.hpp" +#include "../wrapper/repository_wrapper.hpp" + +namespace fs = std::filesystem; + +rm_subcommand::rm_subcommand(const libgit2_object&, CLI::App& app) +{ + auto* rm = app.add_subcommand("rm", "Remove files from the working tree and from the index"); + rm->add_option("", m_pathspec, "Files to remove"); + rm->add_flag("-r", m_recursive, "Allow recursive removal when a leading directory name is given"); + + rm->add_callback([this]() { this->run(); }); +} + +void rm_subcommand::run() +{ + auto directory = get_current_git_path(); + auto repo = repository_wrapper::open(directory); + + index_wrapper index = repo.make_index(); + + std::vector files; + std::vector directories; + + std::for_each(m_pathspec.begin(), m_pathspec.end(), [&](const std::string& path) + { + if (fs::is_directory) + { + directories.push_back(path); + } + else + { + files.push_back(path); + } + }); + + if (!directories.empty() && !m_recursive) + { + std::string msg = "fatal: not removing '" + directories.front() + "' recursively without -r"; + throw git_exception(msg, 128); + } + + index.remove_entries(files); + index.remove_directories(directories); +} diff --git a/src/subcommand/rm_subcommand.hpp b/src/subcommand/rm_subcommand.hpp new file mode 100644 index 0000000..1f575fc --- /dev/null +++ b/src/subcommand/rm_subcommand.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include + +#include "../utils/common.hpp" + +class rm_subcommand +{ +public: + + explicit rm_subcommand(const libgit2_object&, CLI::App& app); + void run(); + +private: + + std::vector m_pathspec; + bool m_recursive = false; +}; + diff --git a/src/wrapper/index_wrapper.cpp b/src/wrapper/index_wrapper.cpp index 4ba0b15..701aab1 100644 --- a/src/wrapper/index_wrapper.cpp +++ b/src/wrapper/index_wrapper.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -47,6 +48,20 @@ void index_wrapper::remove_entry(const std::string& path) throw_if_error(git_index_remove_bypath(*this, path.c_str())); } +void index_wrapper::remove_entries(std::vector paths) +{ + git_strarray_wrapper array{paths}; + throw_if_error(git_index_remove_all(*this, array, NULL, NULL)); +} + +void index_wrapper::remove_directories(std::vector entries) +{ + std::for_each(entries.cbegin(), entries.cend(), [this](const std::string& path) + { + throw_if_error(git_index_remove_directory(*this, path.c_str(), 0)); + }); +} + void index_wrapper::write() { throw_if_error(git_index_write(*this)); diff --git a/src/wrapper/index_wrapper.hpp b/src/wrapper/index_wrapper.hpp index 9091242..9a973cc 100644 --- a/src/wrapper/index_wrapper.hpp +++ b/src/wrapper/index_wrapper.hpp @@ -28,6 +28,8 @@ class index_wrapper : public wrapper_base void add_all(); void remove_entry(const std::string& path); + void remove_entries(std::vector paths); + void remove_directories(std::vector paths); bool has_conflict() const; void output_conflicts();