From 6c343c90caa04faf403fe0e576b648d7213f8cd2 Mon Sep 17 00:00:00 2001 From: Sandrine Pataut Date: Tue, 26 May 2026 11:01:53 +0200 Subject: [PATCH] solve commit bug --- src/wrapper/index_wrapper.cpp | 5 ++++ src/wrapper/index_wrapper.hpp | 2 ++ src/wrapper/repository_wrapper.cpp | 21 ++++++++++++++- test/test_commit.py | 42 ++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/wrapper/index_wrapper.cpp b/src/wrapper/index_wrapper.cpp index d34ce20..9e26725 100644 --- a/src/wrapper/index_wrapper.cpp +++ b/src/wrapper/index_wrapper.cpp @@ -79,6 +79,11 @@ git_oid index_wrapper::write_tree() return tree_id; } +size_t index_wrapper::entry_count() const +{ + return git_index_entrycount(*this); +} + bool index_wrapper::has_conflict() const { return git_index_has_conflicts(*this); diff --git a/src/wrapper/index_wrapper.hpp b/src/wrapper/index_wrapper.hpp index 9a973cc..05d637b 100644 --- a/src/wrapper/index_wrapper.hpp +++ b/src/wrapper/index_wrapper.hpp @@ -23,6 +23,8 @@ class index_wrapper : public wrapper_base void write(); git_oid write_tree(); + size_t entry_count() const; + void add_entry(const std::string& path); void add_entries(std::vector patterns); void add_all(); diff --git a/src/wrapper/repository_wrapper.cpp b/src/wrapper/repository_wrapper.cpp index bf57486..f2ecc83 100644 --- a/src/wrapper/repository_wrapper.cpp +++ b/src/wrapper/repository_wrapper.cpp @@ -293,7 +293,6 @@ void repository_wrapper::create_commit( { if (parents_list) { - // TODO: write a "as_const" function to replace the following auto pl_size = parents_list.value().size(); git_commit** pl_value = parents_list.value(); auto pl_value_const = const_cast(pl_value); @@ -313,9 +312,29 @@ void repository_wrapper::create_commit( }(); index_wrapper index = this->make_index(); + + // Check: initial commit (no parents) with nothing staged + if (parents_count == 0 && index.entry_count() == 0) + { + throw std::runtime_error( + "On branch main\n\nInitial commit\n\nnothing to commit " + "(create/copy files and use \"git add\" to track)" + ); + } + git_oid tree_id = index.write_tree(); index.write(); + // Check: tree is identical to parent tree (nothing changed since last commit) + if (parents_count > 0 && placeholder[0] != nullptr) + { + const git_oid* parent_tree_id = git_commit_tree_id(placeholder[0]); + if (git_oid_equal(&tree_id, parent_tree_id)) + { + throw std::runtime_error("nothing to commit, working tree clean"); + } + } + auto tree = this->tree_lookup(&tree_id); throw_if_error(git_commit_create( diff --git a/test/test_commit.py b/test/test_commit.py index 6b3998e..9314a19 100644 --- a/test/test_commit.py +++ b/test/test_commit.py @@ -81,3 +81,45 @@ def test_commit_message_via_stdin( assert "Author:" in lines[1] assert "Date" in lines[2] assert commit_msg_out in lines[4] + + +def test_commit_no_changes_initial(commit_env_config, git2cpp_path, tmp_path): + """Commit on fresh repo with no staged files should fail""" + cmd_init = [git2cpp_path, "init", "."] + p_init = subprocess.run(cmd_init, capture_output=True, cwd=tmp_path) + assert p_init.returncode == 0 + + # Do NOT add any files — attempt to commit immediately + cmd_commit = [git2cpp_path, "commit", "-m", "empty commit"] + p_commit = subprocess.run(cmd_commit, capture_output=True, cwd=tmp_path, text=True) + + # Should fail: nothing to commit + assert p_commit.returncode != 0 + assert "nothing to commit" in p_commit.stderr or "nothing to commit" in p_commit.stdout + + +def test_commit_no_changes_after_first_commit(commit_env_config, git2cpp_path, tmp_path): + """Commit twice without changes between commits should fail""" + cmd_init = [git2cpp_path, "init", "."] + p_init = subprocess.run(cmd_init, capture_output=True, cwd=tmp_path) + assert p_init.returncode == 0 + + # Create and commit a file + (tmp_path / "file.txt").write_text("hello") + subprocess.run([git2cpp_path, "add", "file.txt"], cwd=tmp_path, check=True) + p_first = subprocess.run( + [git2cpp_path, "commit", "-m", "first commit"], cwd=tmp_path, capture_output=True, text=True + ) + assert p_first.returncode == 0 + + # Try to commit again without any new changes + p_second = subprocess.run( + [git2cpp_path, "commit", "-m", "second commit (no changes)"], + cwd=tmp_path, + capture_output=True, + text=True, + ) + + # Should fail: nothing to commit + assert p_second.returncode != 0 + assert "nothing to commit" in p_second.stderr or "nothing to commit" in p_second.stdout