Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ set(GIT2CPP_SRC
${GIT2CPP_SOURCE_DIR}/subcommand/revlist_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/revparse_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/revparse_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/rm_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/rm_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/stash_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/stash_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/status_subcommand.cpp
Expand Down
4 changes: 3 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "subcommand/status_subcommand.hpp"
#include "subcommand/revparse_subcommand.hpp"
#include "subcommand/revlist_subcommand.hpp"
#include "subcommand/rm_subcommand.hpp"

int main(int argc, char** argv)
{
Expand Down Expand Up @@ -55,8 +56,9 @@ int main(int argc, char** argv)
push_subcommand push(lg2_obj, app);
rebase_subcommand rebase(lg2_obj, app);
remote_subcommand remote(lg2_obj, app);
revparse_subcommand revparse(lg2_obj, app);
revlist_subcommand revlist(lg2_obj, app);
revparse_subcommand revparse(lg2_obj, app);
rm_subcommand rm(lg2_obj, app);
stash_subcommand stash(lg2_obj, app);

app.require_subcommand(/* min */ 0, /* max */ 1);
Expand Down
64 changes: 64 additions & 0 deletions src/subcommand/rm_subcommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <filesystem>
#include <ranges>
#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("<pathspec>", m_pathspec, "Files to remove");
rm->add_flag("-r", m_recursive, "Allow recursive removal when a leading directory name is given");

rm->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<std::string> files;
std::vector<std::string> directories;

std::ranges::for_each(m_pathspec, [&](const std::string& path)
{
if (!fs::exists(path))
{
std::string msg = "fatal: pathspec '" + path + "' did not math any file";
throw git_exception(msg, 128);
}
if (fs::is_directory(path))
{
directories.push_back(path);
}
else
{
if (!repo.does_track(path))
{
std::string msg = "fatal: pathsspec '" + path + "'is not tracked";
throw git_exception(msg, 128);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use the new git2cpp_error_code here.

}
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);
index.write();

std::ranges::for_each(files, [](const std::string& path) { fs::remove(path); });
std::ranges::for_each(directories, [](const std::string& path) { fs::remove_all(path); });
}
21 changes: 21 additions & 0 deletions src/subcommand/rm_subcommand.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include <CLI/CLI.hpp>
#include <string>
#include <vector>

#include "../utils/common.hpp"

class rm_subcommand
{
public:

explicit rm_subcommand(const libgit2_object&, CLI::App& app);
void run();

private:

std::vector<std::string> m_pathspec;
bool m_recursive = false;
};

15 changes: 15 additions & 0 deletions src/wrapper/index_wrapper.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <git2/index.h>
#include <algorithm>
#include <iostream>
#include <vector>

Expand Down Expand Up @@ -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<std::string> paths)
{
git_strarray_wrapper array{paths};
throw_if_error(git_index_remove_all(*this, array, NULL, NULL));
}

void index_wrapper::remove_directories(std::vector<std::string> 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));
Expand Down
2 changes: 2 additions & 0 deletions src/wrapper/index_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class index_wrapper : public wrapper_base<git_index>
void add_all();

void remove_entry(const std::string& path);
void remove_entries(std::vector<std::string> paths);
void remove_directories(std::vector<std::string> paths);

bool has_conflict() const;
void output_conflicts();
Expand Down
7 changes: 7 additions & 0 deletions src/wrapper/repository_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,13 @@ revwalk_wrapper repository_wrapper::new_walker()
return revwalk_wrapper(walker);
}

bool repository_wrapper::does_track(std::string_view path) const
{
unsigned int flags;
throw_if_error(git_status_file(&flags, *this, path.data()));
return !(flags & GIT_STATUS_WT_NEW) && !(flags & GIT_STATUS_IGNORED);
}

// Head

bool repository_wrapper::is_head_unborn() const
Expand Down
2 changes: 2 additions & 0 deletions src/wrapper/repository_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ class repository_wrapper : public wrapper_base<git_repository>

revwalk_wrapper new_walker();

bool does_track(std::string_view path) const;

// Head
bool is_head_unborn() const;
reference_wrapper head() const;
Expand Down
13 changes: 0 additions & 13 deletions src/wrapper/status_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,16 +84,3 @@ auto status_list_wrapper::get_entry_list(git_status_t status) const -> const sta
}
}



// std::ostream& operator<<(std::ostream& out, const status_list_wrapper& slw)
// {
// std::size_t status_list_size = git_status_list_entrycount(slw);
// for (std::size_t i = 0; i < status_list_size; ++i)
// {
// std::cout << i << " ";
// auto entry = git_status_byindex(slw, i);

// }
// return out;
// };
1 change: 1 addition & 0 deletions test/conftest_wasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def pytest_ignore_collect(collection_path: pathlib.Path) -> bool:
"test_reset.py",
"test_revlist.py",
"test_revparse.py",
"test_rm.py",
"test_stash.py",
"test_status.py",
]
Expand Down
Loading