From f42361e118933bf102854724661e82ce6b56271e Mon Sep 17 00:00:00 2001 From: Ian Thomas Date: Thu, 29 May 2025 15:19:49 +0100 Subject: [PATCH 1/2] Add basic `git init` functionality --- src/subcommand/init_subcommand.cpp | 16 ++++--- src/subcommand/init_subcommand.hpp | 2 + src/wrapper/repository_wrapper.cpp | 13 ++---- src/wrapper/repository_wrapper.hpp | 2 +- test/test_git.py | 16 ++++--- test/test_init.py | 67 ++++++++++++++++++++++++++++++ 6 files changed, 93 insertions(+), 23 deletions(-) create mode 100644 test/test_init.py diff --git a/src/subcommand/init_subcommand.cpp b/src/subcommand/init_subcommand.cpp index 349b9c8..c288996 100644 --- a/src/subcommand/init_subcommand.cpp +++ b/src/subcommand/init_subcommand.cpp @@ -1,19 +1,23 @@ +#include #include "init_subcommand.hpp" - -//#include "../wrapper/repository_wrapper.hpp" +#include "../wrapper/repository_wrapper.hpp" InitSubcommand::InitSubcommand(CLI::App& app) { auto *sub = app.add_subcommand("init", "Explanation of init here"); - sub->add_flag("--bare", bare, "--- bare ---"); + sub->add_flag("--bare", bare, "info about bare arg"); + + // If directory not specified, uses cwd. + sub->add_option("directory", directory, "info about directory arg") + ->check(CLI::ExistingDirectory | CLI::NonexistentPath) + ->default_val(std::filesystem::current_path()); sub->callback([this]() { this->run(); }); } void InitSubcommand::run() { - std::cout << "RUN " << bare << std::endl; - //RepositoryWrapper repo; - //repo.init(bare); + RepositoryWrapper repo; + repo.init(directory, bare); } diff --git a/src/subcommand/init_subcommand.hpp b/src/subcommand/init_subcommand.hpp index 098ce0b..a27e06c 100644 --- a/src/subcommand/init_subcommand.hpp +++ b/src/subcommand/init_subcommand.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include "base_subcommand.hpp" class InitSubcommand : public BaseSubcommand @@ -10,4 +11,5 @@ class InitSubcommand : public BaseSubcommand private: bool bare; + std::string directory; }; diff --git a/src/wrapper/repository_wrapper.cpp b/src/wrapper/repository_wrapper.cpp index d28ceea..8788bb3 100644 --- a/src/wrapper/repository_wrapper.cpp +++ b/src/wrapper/repository_wrapper.cpp @@ -15,15 +15,8 @@ RepositoryWrapper::~RepositoryWrapper() } } -void RepositoryWrapper::init(bool bare) +void RepositoryWrapper::init(const std::string& directory, bool bare) { - std::cout << "repo init - start" << std::endl; - - // what if it is already initialised??? - - // convert error code to exception - std::string path = "repo"; - throwIfError(git_repository_init(&_repo, path.c_str(), bare)); - - std::cout << "repo init - end " << std::endl; + // what if it is already initialised? Throw exception or delete and recreate? + throwIfError(git_repository_init(&_repo, directory.c_str(), bare)); } diff --git a/src/wrapper/repository_wrapper.hpp b/src/wrapper/repository_wrapper.hpp index 55c5c43..3e4cbb8 100644 --- a/src/wrapper/repository_wrapper.hpp +++ b/src/wrapper/repository_wrapper.hpp @@ -9,7 +9,7 @@ class RepositoryWrapper : public BaseWrapper virtual ~RepositoryWrapper(); - void init(bool bare); + void init(const std::string& directory, bool bare); private: git_repository *_repo; diff --git a/test/test_git.py b/test/test_git.py index 3f9a3c2..08bece8 100644 --- a/test/test_git.py +++ b/test/test_git.py @@ -1,15 +1,19 @@ +import pytest import subprocess -def test_version(): - cmd = ['build/git2cpp', '-v'] + +@pytest.mark.parametrize("arg", ['-v', '--version']) +def test_version(arg): + cmd = ['build/git2cpp', arg] p = subprocess.run(cmd, capture_output=True) assert p.returncode == 0 - assert len(p.stderr) == 0 + assert p.stderr == b'' assert p.stdout.startswith(b'git2cpp ') -def test_unknown_option(): + +def test_error_on_unknown_option(): cmd = ['build/git2cpp', '--unknown'] p = subprocess.run(cmd, capture_output=True) - #assert p.returncode == 1 - assert len(p.stdout) == 0 + assert p.returncode == 1 + assert p.stdout == b'' assert p.stderr.startswith(b"The following argument was not expected: --unknown") diff --git a/test/test_init.py b/test/test_init.py new file mode 100644 index 0000000..884ce21 --- /dev/null +++ b/test/test_init.py @@ -0,0 +1,67 @@ +import os +from pathlib import Path +import pytest +import subprocess + + +# Fixture to run test in current tmp_path +@pytest.fixture +def run_in_tmp_path(tmp_path): + original_cwd = os.getcwd() + os.chdir(tmp_path) + yield + os.chdir(original_cwd) + + +def test_init_in_directory(tmp_path): + # tmp_path exists and is empty. + assert list(tmp_path.iterdir()) == [] + + cmd = ['/Users/iant/github/git2cpp/build/git2cpp', '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 sorted(map(lambda path: path.name, tmp_path.iterdir())) == [ + 'HEAD', 'config', 'description', 'hooks', 'info', 'objects', 'refs' + ] + + # TODO: check this is a valid git repo + + +def test_init_in_cwd(tmp_path, run_in_tmp_path): + # tmp_path exists and is empty. + assert list(tmp_path.iterdir()) == [] + assert Path.cwd() == tmp_path + + cmd = ['/Users/iant/github/git2cpp/build/git2cpp', 'init', '--bare'] + p = subprocess.run(cmd, capture_output=True) + assert p.returncode == 0 + 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' + ] + + # TODO: check this is a valid git repo + + +# TODO: Test without bare flag. + + +def test_error_on_unknown_option(): + cmd = ['build/git2cpp', 'init', '--unknown'] + p = subprocess.run(cmd, capture_output=True) + assert p.returncode == 1 + assert p.stdout == b'' + assert p.stderr.startswith(b"The following argument was not expected: --unknown") + + +def test_error_on_repeated_directory(): + cmd = ['build/git2cpp', 'init', 'abc', 'def'] + p = subprocess.run(cmd, capture_output=True) + assert p.returncode == 1 + assert p.stdout == b'' + assert p.stderr.startswith(b"The following argument was not expected: def") From f0ea04f26a9be4c162ca1ff6efedc2aaaa258879 Mon Sep 17 00:00:00 2001 From: Ian Thomas Date: Thu, 29 May 2025 15:37:04 +0100 Subject: [PATCH 2/2] Use correct run-time path to git2cpp binary --- test/conftest.py | 17 +++++++++++++++++ test/test_git.py | 8 ++++---- test/test_init.py | 27 ++++++++------------------- 3 files changed, 29 insertions(+), 23 deletions(-) create mode 100644 test/conftest.py diff --git a/test/conftest.py b/test/conftest.py new file mode 100644 index 0000000..5f8435e --- /dev/null +++ b/test/conftest.py @@ -0,0 +1,17 @@ +import os +from pathlib import Path +import pytest + + +# Fixture to run test in current tmp_path +@pytest.fixture +def run_in_tmp_path(tmp_path): + original_cwd = os.getcwd() + os.chdir(tmp_path) + yield + os.chdir(original_cwd) + + +@pytest.fixture(scope='session') +def git2cpp_path(): + return Path(__file__).parent.parent / 'build' / 'git2cpp' diff --git a/test/test_git.py b/test/test_git.py index 08bece8..899c054 100644 --- a/test/test_git.py +++ b/test/test_git.py @@ -3,16 +3,16 @@ @pytest.mark.parametrize("arg", ['-v', '--version']) -def test_version(arg): - cmd = ['build/git2cpp', arg] +def test_version(git2cpp_path, arg): + cmd = [git2cpp_path, arg] p = subprocess.run(cmd, capture_output=True) assert p.returncode == 0 assert p.stderr == b'' assert p.stdout.startswith(b'git2cpp ') -def test_error_on_unknown_option(): - cmd = ['build/git2cpp', '--unknown'] +def test_error_on_unknown_option(git2cpp_path): + cmd = [git2cpp_path, '--unknown'] p = subprocess.run(cmd, capture_output=True) assert p.returncode == 1 assert p.stdout == b'' diff --git a/test/test_init.py b/test/test_init.py index 884ce21..8f0ce9a 100644 --- a/test/test_init.py +++ b/test/test_init.py @@ -1,23 +1,12 @@ -import os from pathlib import Path -import pytest import subprocess -# Fixture to run test in current tmp_path -@pytest.fixture -def run_in_tmp_path(tmp_path): - original_cwd = os.getcwd() - os.chdir(tmp_path) - yield - os.chdir(original_cwd) - - -def test_init_in_directory(tmp_path): +def test_init_in_directory(git2cpp_path, tmp_path): # tmp_path exists and is empty. assert list(tmp_path.iterdir()) == [] - cmd = ['/Users/iant/github/git2cpp/build/git2cpp', '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'' @@ -30,12 +19,12 @@ def test_init_in_directory(tmp_path): # TODO: check this is a valid git repo -def test_init_in_cwd(tmp_path, run_in_tmp_path): +def test_init_in_cwd(git2cpp_path, tmp_path, run_in_tmp_path): # tmp_path exists and is empty. assert list(tmp_path.iterdir()) == [] assert Path.cwd() == tmp_path - cmd = ['/Users/iant/github/git2cpp/build/git2cpp', 'init', '--bare'] + cmd = [git2cpp_path, 'init', '--bare'] p = subprocess.run(cmd, capture_output=True) assert p.returncode == 0 assert p.stdout == b'' @@ -51,16 +40,16 @@ def test_init_in_cwd(tmp_path, run_in_tmp_path): # TODO: Test without bare flag. -def test_error_on_unknown_option(): - cmd = ['build/git2cpp', 'init', '--unknown'] +def test_error_on_unknown_option(git2cpp_path): + cmd = [git2cpp_path, 'init', '--unknown'] p = subprocess.run(cmd, capture_output=True) assert p.returncode == 1 assert p.stdout == b'' assert p.stderr.startswith(b"The following argument was not expected: --unknown") -def test_error_on_repeated_directory(): - cmd = ['build/git2cpp', 'init', 'abc', 'def'] +def test_error_on_repeated_directory(git2cpp_path): + cmd = [git2cpp_path, 'init', 'abc', 'def'] p = subprocess.run(cmd, capture_output=True) assert p.returncode == 1 assert p.stdout == b''