Skip to content

feat: add add subcommand #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 17, 2025
Merged
Show file tree
Hide file tree
Changes from 8 commits
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 .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
build/
__pycache__/
.cache/
compile_commands.json
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ find_package(libgit2)
# =====

set(GIT2CPP_SRC
${GIT2CPP_SOURCE_DIR}/subcommand/add_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/add_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/init_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/init_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/status_subcommand.cpp
Expand All @@ -47,6 +49,8 @@ set(GIT2CPP_SRC
${GIT2CPP_SOURCE_DIR}/utils/common.hpp
${GIT2CPP_SOURCE_DIR}/utils/git_exception.cpp
${GIT2CPP_SOURCE_DIR}/utils/git_exception.hpp
${GIT2CPP_SOURCE_DIR}/wrapper/index_wrapper.cpp
${GIT2CPP_SOURCE_DIR}/wrapper/index_wrapper.hpp
${GIT2CPP_SOURCE_DIR}/wrapper/refs_wrapper.cpp
${GIT2CPP_SOURCE_DIR}/wrapper/refs_wrapper.hpp
${GIT2CPP_SOURCE_DIR}/wrapper/repository_wrapper.cpp
Expand All @@ -59,4 +63,3 @@ set(GIT2CPP_SRC

add_executable(git2cpp ${GIT2CPP_SRC})
target_link_libraries(git2cpp PRIVATE libgit2::libgit2package)

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Developer's workflow using `micromamba` to manage the dependencies:
```bash
micromamba create -f dev-environment.yml
micromamba activate git2cpp-dev
cmake -Bbuild $CMAKE_INSALL_PREFIX=$CONDA_PREFIX
cmake -Bbuild -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX
cd build
make -j8
```
Expand Down
2 changes: 1 addition & 1 deletion dev-environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ channels:
dependencies:
- cli11
- libgit2
- meson
- cmake
- pkg-config
- python
- pytest
Expand Down
2 changes: 2 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "utils/git_exception.hpp"
#include "version.hpp"
#include "subcommand/add_subcommand.hpp"
#include "subcommand/init_subcommand.hpp"
#include "subcommand/status_subcommand.hpp"

Expand All @@ -21,6 +22,7 @@ int main(int argc, char** argv)
// Sub commands
init_subcommand init(lg2_obj, app);
status_subcommand status(lg2_obj, app);
add_subcommand add(lg2_obj, app);

app.parse(argc, argv);

Expand Down
39 changes: 39 additions & 0 deletions src/subcommand/add_subcommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <git2.h>

#include "add_subcommand.hpp"
#include "../wrapper/index_wrapper.hpp"
#include "../wrapper/repository_wrapper.hpp"


add_subcommand::add_subcommand(const libgit2_object&, CLI::App& app)
{
auto *sub = app.add_subcommand("add", "Add file contents to the index");

sub->add_option("files", add_files, "Files to add");

sub->add_flag("-A,--all,--no-ignore-removal", all_flag, "");
// sub->add_flag("-n,--dryrun", dryrun_flag, "");
// sub->add_flag("-u,--update", update_flag, "");
// sub->add_flag("-v,--verbose", verbose_flag, "");

sub->callback([this]() { this->run(); });
};


void add_subcommand::run()
{
auto directory = get_current_git_path();
auto bare = false;
auto repo = repository_wrapper::init(directory, bare);

index_wrapper index = repo.make_index();

if (all_flag)
{
index.add_all();
}
else
{
index.add_entries(add_files);
}
}
17 changes: 17 additions & 0 deletions src/subcommand/add_subcommand.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include <CLI/CLI.hpp>

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

class add_subcommand
{
public:

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

private:
bool all_flag = false;
std::vector<std::string> add_files;
Copy link
Member

Choose a reason for hiding this comment

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

Convention: data member names should start with m_ (or p_) so it is easy to distinguish them from local variables.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

m_ stands for "member" and p_ stands for what ?

Copy link
Member

Choose a reason for hiding this comment

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

pointer

};
7 changes: 1 addition & 6 deletions src/subcommand/status_subcommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@
status_subcommand::status_subcommand(const libgit2_object&, CLI::App& app)
{
auto *sub = app.add_subcommand("status", "Show modified files in working directory, staged for your next commit");
// Displays paths that have differences between the index file and the current HEAD commit,
// paths that have differences between the working tree and the index file, and paths in the
// working tree that are not tracked by Git (and are not ignored by gitignore[5]).
// The first are what you would commit by running git commit;
// the second and third are what you could commit by running git add before running git commit.

sub->add_flag("-s,--short", short_flag, "Give the output in the short-format.");
sub->add_flag("--long", long_flag, "Give the output in the long-format. This is the default.");
Expand Down Expand Up @@ -152,7 +147,7 @@ void print_entries(std::vector<print_entry> entries_to_print)
}
}

void print_not_tracked(std::vector<print_entry> entries_to_print, const std::set<std::string>& tracked_dir_set,
void print_not_tracked(const std::vector<print_entry>& entries_to_print, const std::set<std::string>& tracked_dir_set,
std::set<std::string>& untracked_dir_set)
{
std::vector<print_entry> not_tracked_entries_to_print{};
Expand Down
2 changes: 1 addition & 1 deletion src/utils/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class wrapper_base
wrapper_base& operator=(wrapper_base&& rhs)
{
std::swap(p_resource, rhs.p_resource);
return this;
return *this;
}

operator resource_type*() const noexcept
Expand Down
4 changes: 0 additions & 4 deletions src/utils/meson.build

This file was deleted.

2 changes: 1 addition & 1 deletion src/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#define GIT2CPP_VERSION_MAJOR 0
#define GIT2CPP_VERSION_MINOR 0
#define GIT2CPP_VERSION_PATCH 1
#define GIT2CPP_VERSION_PATCH 2
Copy link
Member

Choose a reason for hiding this comment

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

Why updating the version?

Copy link
Collaborator Author

@SandrineP SandrineP Jul 17, 2025

Choose a reason for hiding this comment

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

The 0.0.2 has been released but we forgot to change it there, so it's to catch up.


// e.g. ".rc0"
#define GIT2CPP_VERSION_SUFFIX
Expand Down
35 changes: 35 additions & 0 deletions src/wrapper/index_wrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "index_wrapper.hpp"
#include "../utils/git_exception.hpp"
#include "../wrapper/repository_wrapper.hpp"

#include <vector>

index_wrapper::~index_wrapper()
{
git_index_free(p_resource);
p_resource=nullptr;
}

index_wrapper index_wrapper::init(repository_wrapper& rw)
{
index_wrapper index;
throwIfError(git_repository_index(&(index.p_resource), rw));
return index;
}

void index_wrapper::add_entries(std::vector<std::string> patterns)
{
add_impl(std::move(patterns));
}

void index_wrapper::add_all()
{
add_impl({{"."}});
}

void index_wrapper::add_impl(std::vector<std::string> patterns)
{
git_strarray_wrapper array=git_strarray_wrapper(patterns);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
git_strarray_wrapper array=git_strarray_wrapper(patterns);
git_strarray_wrapper array{patterns};

throwIfError(git_index_add_all(*this, array, 0, NULL, NULL));
throwIfError(git_index_write(*this));
}
31 changes: 31 additions & 0 deletions src/wrapper/index_wrapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <string>
#include <vector>

#include <git2.h>

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

class repository_wrapper;

class index_wrapper : public wrapper_base<git_index>
{
public:

~index_wrapper();

index_wrapper(index_wrapper&&) = default;
index_wrapper& operator=(index_wrapper&&) = default;

static index_wrapper init(repository_wrapper& rw);

void add_entries(std::vector<std::string> patterns);
void add_all();


private:

index_wrapper() = default;
void add_impl(std::vector<std::string> patterns);
};
9 changes: 7 additions & 2 deletions src/wrapper/repository_wrapper.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include "../utils/git_exception.hpp"
#include "repository_wrapper.hpp"

#include "../utils/git_exception.hpp"

repository_wrapper::~repository_wrapper()
{
Expand All @@ -21,3 +20,9 @@ repository_wrapper repository_wrapper::init(const std::string& directory, bool b
throwIfError(git_repository_init(&(rw.p_resource), directory.c_str(), bare));
return rw;
}

index_wrapper repository_wrapper::make_index()
{
index_wrapper index = index_wrapper::init(*this);
return index;
}
2 changes: 2 additions & 0 deletions src/wrapper/repository_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <git2.h>

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

class repository_wrapper : public wrapper_base<git_repository>
{
Expand All @@ -17,6 +18,7 @@ class repository_wrapper : public wrapper_base<git_repository>

static repository_wrapper init(const std::string& directory, bool bare);
static repository_wrapper open(const std::string& directory);
index_wrapper make_index();

private:

Expand Down
Empty file modified test/data/status_data/embeded_git/config
100644 → 100755
Empty file.
36 changes: 36 additions & 0 deletions test/test_add.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import os
import subprocess

import pytest


@pytest.mark.parametrize("all_flag", ["", "-A", "--all", "--no-ignore-removal"])
def test_add(git2cpp_path, all_flag):
with open("./test/mook_file.txt", "x") as f:
pass
f.close()
Copy link
Member

Choose a reason for hiding this comment

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

This line isn't needed as the f will be automatically closed when the with ... block is exited. The same applies to 4 lines below.


with open("./test/mook_file_2.txt", "x") as f:
pass
f.close()

cmd_add = [git2cpp_path, 'add']
if all_flag != "":
cmd_add.append(all_flag)
else:
cmd_add.append("test/mook_file.txt")
subprocess.run(cmd_add, capture_output=True, text=True)

cmd_status = [git2cpp_path, 'status', "--long"]
p_status = subprocess.run(cmd_status, capture_output=True, text=True)

assert "Changes to be committed" in p_status.stdout
assert "new file" in p_status.stdout
if all_flag != "":
assert "Untracked files" not in p_status.stdout
else:
assert "Untracked files" in p_status.stdout

os.remove("./test/mook_file.txt")
os.remove("./test/mook_file_2.txt")
subprocess.run(cmd_add, capture_output=True, text=True)
Copy link
Member

Choose a reason for hiding this comment

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

Is this line just to undo the add, to leave the test directory at the end the same as it was at the start? If so can you add a comment saying this, otherwise it will look suspicious in future to have this line without any following assert.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, that's the reason why ! I'll write a comment.