Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ set(GIT2CPP_SRC
${GIT2CPP_SOURCE_DIR}/subcommand/remote_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/reset_subcommand.cpp
${GIT2CPP_SOURCE_DIR}/subcommand/reset_subcommand.hpp
${GIT2CPP_SOURCE_DIR}/subcommand/revlist_subcommand.cpp
${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/status_subcommand.cpp
Expand Down Expand Up @@ -96,6 +98,8 @@ set(GIT2CPP_SRC
${GIT2CPP_SOURCE_DIR}/wrapper/remote_wrapper.hpp
${GIT2CPP_SOURCE_DIR}/wrapper/repository_wrapper.cpp
${GIT2CPP_SOURCE_DIR}/wrapper/repository_wrapper.hpp
${GIT2CPP_SOURCE_DIR}/wrapper/revwalk_wrapper.cpp
${GIT2CPP_SOURCE_DIR}/wrapper/revwalk_wrapper.hpp
${GIT2CPP_SOURCE_DIR}/wrapper/signature_wrapper.cpp
${GIT2CPP_SOURCE_DIR}/wrapper/signature_wrapper.hpp
${GIT2CPP_SOURCE_DIR}/wrapper/status_wrapper.cpp
Expand Down
4 changes: 3 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "subcommand/reset_subcommand.hpp"
#include "subcommand/status_subcommand.hpp"
#include "subcommand/revparse_subcommand.hpp"
#include "subcommand/revlist_subcommand.hpp"

int main(int argc, char** argv)
{
Expand All @@ -45,7 +46,8 @@ int main(int argc, char** argv)
merge_subcommand merge(lg2_obj, app);
push_subcommand push(lg2_obj, app);
remote_subcommand remote(lg2_obj, app);
revparse_subcommand rev(lg2_obj, app);
revparse_subcommand revparse(lg2_obj, app);
revlist_subcommand revlist(lg2_obj, app);

app.require_subcommand(/* min */ 0, /* max */ 1);

Expand Down
15 changes: 9 additions & 6 deletions src/subcommand/log_subcommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,25 @@ void log_subcommand::run()
auto repo = repository_wrapper::open(directory);
// auto branch_name = repo.head().short_name();

git_revwalk* walker;
git_revwalk_new(&walker, repo);
git_revwalk_push_head(walker);
if (repo.is_head_unborn())
{
std::cout << "fatal: your current branch 'main' does not have any commits yet" << std::endl;
return;
}

revwalk_wrapper walker = repo.new_walker();
walker.push_head();

terminal_pager pager;

std::size_t i=0;
git_oid commit_oid;
while (!git_revwalk_next(&commit_oid, walker) && i<m_max_count_flag)
while (!walker.next(commit_oid) && i<m_max_count_flag)
{
commit_wrapper commit = repo.find_commit(commit_oid);
print_commit(commit, m_format_flag);
++i;
}

git_revwalk_free(walker);

pager.show();
}
45 changes: 45 additions & 0 deletions src/subcommand/revlist_subcommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "revlist_subcommand.hpp"
#include "../wrapper/repository_wrapper.hpp"
#include "../wrapper/revwalk_wrapper.hpp"

revlist_subcommand::revlist_subcommand(const libgit2_object&, CLI::App& app)
{
auto* sub = app.add_subcommand("rev-list", "Lists commit objects in reverse chronological order");

sub->add_option("<commit>", m_commit, "");
sub->add_option("-n,--max-count", m_max_count_flag, "Limit the output to <number> commits.");

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

void revlist_subcommand::run()
{
if (m_commit.empty())
{
throw std::runtime_error("usage: git rev-list [<options>] <commit>... [--] [<path>...]"); // TODO: add help info
}

auto directory = get_current_git_path();
auto repo = repository_wrapper::open(directory);
git_oid start_commit_oid;
int not_sha1 = git_oid_fromstrp(&start_commit_oid, m_commit.c_str());
if (not_sha1)
{
commit_wrapper start_commit = repo.find_commit(m_commit);
start_commit_oid = start_commit.oid();
}

revwalk_wrapper walker = repo.new_walker();
walker.push(start_commit_oid);

std::size_t i=0;
git_oid commit_oid;
char buf[GIT_OID_SHA1_HEXSIZE + 1];
while (!walker.next(commit_oid) && i<m_max_count_flag)
{
git_oid_fmt(buf, &commit_oid);
buf[GIT_OID_SHA1_HEXSIZE] = '\0';
std::cout << buf << std::endl;
++i;
}
}
20 changes: 20 additions & 0 deletions src/subcommand/revlist_subcommand.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

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

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

class revlist_subcommand
{
public:

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

private:

std::string m_commit;
int m_max_count_flag=std::numeric_limits<int>::max();

};
10 changes: 9 additions & 1 deletion src/subcommand/status_subcommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ void status_subcommand::run()
{
std::cout << "On branch " << branch_name << "\n" << std::endl;

if (repo.is_head_unborn())
{
std::cout << "No commits yet\n" << std::endl;
}

if (sl.has_unmerged_header())
{
std::cout << "You have unmerged paths.\n (fix conflicts and run \"git commit\")\n (use \"git merge --abort\" to abort the merge)\n" << std::endl;
Expand Down Expand Up @@ -274,6 +279,9 @@ void status_subcommand::run()
// TODO: check if this message should be displayed even if there are untracked files
if (!(sl.has_tobecommited_header() | sl.has_notstagged_header() | sl.has_unmerged_header() | sl.has_untracked_header()))
{
std::cout << treeclean_message << std::endl;
if (is_long)
{
std::cout << treeclean_message << std::endl;
}
}
}
14 changes: 7 additions & 7 deletions src/wrapper/repository_wrapper.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
#include <iostream>

#include "../utils/git_exception.hpp"
#include "../wrapper/index_wrapper.hpp"
#include "../wrapper/object_wrapper.hpp"
#include "../wrapper/commit_wrapper.hpp"
#include "../wrapper/remote_wrapper.hpp"
#include <git2/repository.h>
#include <git2/remote.h>
#include "../wrapper/repository_wrapper.hpp"

repository_wrapper::~repository_wrapper()
Expand Down Expand Up @@ -56,6 +49,13 @@ bool repository_wrapper::is_shallow() const
return git_repository_is_shallow(*this);
}

revwalk_wrapper repository_wrapper::new_walker()
{
git_revwalk* walker;
throw_if_error(git_revwalk_new(&walker, *this));
return revwalk_wrapper(walker);
}

// Head

bool repository_wrapper::is_head_unborn() const
Expand Down
3 changes: 3 additions & 0 deletions src/wrapper/repository_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "../wrapper/object_wrapper.hpp"
#include "../wrapper/refs_wrapper.hpp"
#include "../wrapper/remote_wrapper.hpp"
#include "../wrapper/revwalk_wrapper.hpp"
#include "../wrapper/signature_wrapper.hpp"
#include "../wrapper/wrapper_base.hpp"

Expand All @@ -36,6 +37,8 @@ class repository_wrapper : public wrapper_base<git_repository>
bool is_bare() const;
bool is_shallow() const;

revwalk_wrapper new_walker();

// Head
bool is_head_unborn() const;
reference_wrapper head() const;
Expand Down
31 changes: 31 additions & 0 deletions src/wrapper/revwalk_wrapper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <git2/index.h>
#include <git2/types.h>

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

revwalk_wrapper::revwalk_wrapper(git_revwalk* walker)
: base_type(walker)
{
}

revwalk_wrapper::~revwalk_wrapper()
{
git_revwalk_free(p_resource);
p_resource=nullptr;
}

void revwalk_wrapper::push_head()
{
throw_if_error(git_revwalk_push_head(*this));
}

void revwalk_wrapper::push(git_oid& commit_oid)
{
throw_if_error(git_revwalk_push(*this, &commit_oid));
}

int revwalk_wrapper::next(git_oid& commit_oid)
{
return git_revwalk_next(&commit_oid, *this);
}
29 changes: 29 additions & 0 deletions src/wrapper/revwalk_wrapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include <git2.h>
#include <git2/types.h>

#include "../wrapper/wrapper_base.hpp"
#include "../wrapper/commit_wrapper.hpp"

class revwalk_wrapper : public wrapper_base<git_revwalk>
{
public:

using base_type = wrapper_base<git_revwalk>;

~revwalk_wrapper();

revwalk_wrapper(revwalk_wrapper&&) noexcept = default;
revwalk_wrapper& operator=(revwalk_wrapper&&) noexcept = default;

void push_head();
void push(git_oid& commit_oid);
int next(git_oid& commit_oid);

private:

revwalk_wrapper(git_revwalk* walker);

friend class repository_wrapper;
};
63 changes: 40 additions & 23 deletions test/test_init.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
from pathlib import Path
import subprocess
from pathlib import Path


def test_init_in_directory(git2cpp_path, tmp_path):
# tmp_path exists and is empty.
assert list(tmp_path.iterdir()) == []

cmd = [git2cpp_path, 'init', '--bare', str(tmp_path)]
cmd = [git2cpp_path, "init", "--bare", str(tmp_path)]
p = subprocess.run(cmd, capture_output=True)
assert p.returncode == 0
assert p.stdout == b''
assert p.stderr == b''
assert p.stdout == b""
assert p.stderr == b""

assert sorted(map(lambda path: path.name, tmp_path.iterdir())) == [
'HEAD', 'config', 'description', 'hooks', 'info', 'objects', 'refs'
"HEAD",
"config",
"description",
"hooks",
"info",
"objects",
"refs",
]

# TODO: check this is a valid git repo
Expand All @@ -24,14 +30,20 @@ def test_init_in_cwd(git2cpp_path, tmp_path, run_in_tmp_path):
assert list(tmp_path.iterdir()) == []
assert Path.cwd() == tmp_path

cmd = [git2cpp_path, 'init', '--bare']
cmd = [git2cpp_path, "init", "--bare"]
p = subprocess.run(cmd, capture_output=True)
assert p.returncode == 0
assert p.stdout == b''
assert p.stderr == b''
assert p.stdout == b""
assert p.stderr == b""

assert sorted(map(lambda path: path.name, tmp_path.iterdir())) == [
'HEAD', 'config', 'description', 'hooks', 'info', 'objects', 'refs'
"HEAD",
"config",
"description",
"hooks",
"info",
"objects",
"refs",
]

# TODO: check this is a valid git repo
Expand All @@ -41,38 +53,43 @@ def test_init_not_bare(git2cpp_path, tmp_path):
# tmp_path exists and is empty.
assert list(tmp_path.iterdir()) == []

cmd = [git2cpp_path, 'init', '.']
cmd = [git2cpp_path, "init", "."]
p = subprocess.run(cmd, capture_output=True, cwd=tmp_path)
assert p.returncode == 0
assert p.stdout == b''
assert p.stderr == b''
assert p.stdout == b""
assert p.stderr == b""

# Directory contains just .git directory.
assert sorted(map(lambda path: path.name, tmp_path.iterdir())) == ['.git']
# Directory contains just .git directory.
assert sorted(map(lambda path: path.name, tmp_path.iterdir())) == [".git"]
# .git directory is a valid repo.
assert sorted(map(lambda path: path.name, (tmp_path / '.git').iterdir())) == [
'HEAD', 'config', 'description', 'hooks', 'info', 'objects', 'refs'
assert sorted(map(lambda path: path.name, (tmp_path / ".git").iterdir())) == [
"HEAD",
"config",
"description",
"hooks",
"info",
"objects",
"refs",
]

# Would like to use `git2cpp status` but it complains that 'refs/heads/master' not found
cmd = [git2cpp_path, 'log']
cmd = [git2cpp_path, "log"]
p = subprocess.run(cmd, capture_output=True, cwd=tmp_path)
assert p.returncode == 0
assert p.stdout == b''
assert p.stderr == b''
assert b"does not have any commits yet" in p.stdout


def test_error_on_unknown_option(git2cpp_path):
cmd = [git2cpp_path, 'init', '--unknown']
cmd = [git2cpp_path, "init", "--unknown"]
p = subprocess.run(cmd, capture_output=True)
assert p.returncode == 109
assert p.stdout == b''
assert p.stdout == b""
assert p.stderr.startswith(b"The following argument was not expected: --unknown")


def test_error_on_repeated_directory(git2cpp_path):
cmd = [git2cpp_path, 'init', 'abc', 'def']
cmd = [git2cpp_path, "init", "abc", "def"]
p = subprocess.run(cmd, capture_output=True)
assert p.returncode == 109
assert p.stdout == b''
assert p.stdout == b""
assert p.stderr.startswith(b"The following argument was not expected: def")
20 changes: 20 additions & 0 deletions test/test_revlist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import subprocess

import pytest


def test_revlist(xtl_clone, git_config, git2cpp_path, tmp_path, monkeypatch):
assert (tmp_path / "xtl").exists()
xtl_path = tmp_path / "xtl"

cmd = [
git2cpp_path,
"rev-list",
"35955995424eb9699bb604b988b5270253b1fccc",
"--max-count",
"2",
]
p = subprocess.run(cmd, capture_output=True, cwd=xtl_path, text=True)
assert p.returncode == 0
assert "da1754dd6" in p.stdout
assert "2da8e13ef" not in p.stdout
Loading