Skip to content

Commit dbd11b0

Browse files
authored
Minimal clone command (#25)
1 parent cd44cf1 commit dbd11b0

File tree

7 files changed

+83
-2
lines changed

7 files changed

+83
-2
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ set(GIT2CPP_SRC
4545
${GIT2CPP_SOURCE_DIR}/subcommand/branch_subcommand.hpp
4646
${GIT2CPP_SOURCE_DIR}/subcommand/checkout_subcommand.cpp
4747
${GIT2CPP_SOURCE_DIR}/subcommand/checkout_subcommand.hpp
48+
${GIT2CPP_SOURCE_DIR}/subcommand/clone_subcommand.cpp
49+
${GIT2CPP_SOURCE_DIR}/subcommand/clone_subcommand.hpp
4850
${GIT2CPP_SOURCE_DIR}/subcommand/init_subcommand.cpp
4951
${GIT2CPP_SOURCE_DIR}/subcommand/init_subcommand.hpp
5052
${GIT2CPP_SOURCE_DIR}/subcommand/status_subcommand.cpp

src/main.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "subcommand/add_subcommand.hpp"
88
#include "subcommand/branch_subcommand.hpp"
99
#include "subcommand/checkout_subcommand.hpp"
10+
#include "subcommand/clone_subcommand.hpp"
1011
#include "subcommand/init_subcommand.hpp"
1112
#include "subcommand/status_subcommand.hpp"
1213

@@ -25,8 +26,11 @@ int main(int argc, char** argv)
2526
init_subcommand init(lg2_obj, app);
2627
status_subcommand status(lg2_obj, app);
2728
add_subcommand add(lg2_obj, app);
28-
branch_subcommand(lg2_obj, app);
29-
checkout_subcommand(lg2_obj, app);
29+
branch_subcommand branch(lg2_obj, app);
30+
checkout_subcommand checkout(lg2_obj, app);
31+
clone_subcommand clone(lg2_obj, app);
32+
33+
app.require_subcommand(/* min */ 0, /* max */ 1);
3034

3135
CLI11_PARSE(app, argc, argv);
3236

src/subcommand/clone_subcommand.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <iostream>
2+
3+
#include "../subcommand/clone_subcommand.hpp"
4+
#include "../wrapper/repository_wrapper.hpp"
5+
6+
clone_subcommand::clone_subcommand(const libgit2_object&, CLI::App& app)
7+
{
8+
auto* sub = app.add_subcommand("clone", "Clone a directory into a new repository");
9+
10+
sub->add_option("<repository>", m_repository, "The (possibly remote) repository to clone from.")->required();
11+
sub->add_option("<directory>", m_directory, "The name of a new directory to clone into.");
12+
13+
sub->callback([this]() { this->run(); });
14+
}
15+
16+
void clone_subcommand::run()
17+
{
18+
git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
19+
std::string short_name = m_directory;
20+
if (m_directory.empty())
21+
{
22+
auto size = m_repository.size();
23+
auto begin = m_repository.find_last_of('/') + 1;
24+
auto end = m_repository.ends_with(".git") ? size - 4 : size;
25+
auto count = end - begin;
26+
short_name = m_repository.substr(begin, count);
27+
m_directory = get_current_git_path() + '/' + short_name;
28+
}
29+
std::cout << "Cloning into '" + short_name + "'..." << std::endl;
30+
repository_wrapper::clone(m_repository, m_directory, opts);
31+
}

src/subcommand/clone_subcommand.hpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
3+
#include <CLI/CLI.hpp>
4+
5+
#include "../utils/common.hpp"
6+
7+
class clone_subcommand
8+
{
9+
public:
10+
11+
explicit clone_subcommand(const libgit2_object&, CLI::App& app);
12+
void run();
13+
14+
private:
15+
16+
std::string m_repository = {};
17+
std::string m_directory = {};
18+
};

src/wrapper/repository_wrapper.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ repository_wrapper repository_wrapper::init(std::string_view directory, bool bar
2121
return rw;
2222
}
2323

24+
repository_wrapper repository_wrapper::clone(std::string_view url, std::string_view path, const git_clone_options& opts)
25+
{
26+
repository_wrapper rw;
27+
throw_if_error(git_clone(&(rw.p_resource), url.data(), path.data(), &opts));
28+
return rw;
29+
}
30+
2431
git_repository_state_t repository_wrapper::state() const
2532
{
2633
return git_repository_state_t(git_repository_state(*this));

src/wrapper/repository_wrapper.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class repository_wrapper : public wrapper_base<git_repository>
2626

2727
static repository_wrapper init(std::string_view directory, bool bare);
2828
static repository_wrapper open(std::string_view directory);
29+
static repository_wrapper clone(std::string_view url, std::string_view path, const git_clone_options& opts);
2930

3031
git_repository_state_t state() const;
3132

test/test_clone.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import os
2+
import subprocess
3+
4+
import pytest
5+
6+
def test_clone(git2cpp_path):
7+
url = 'https://github.com/xtensor-stack/xtl.git'
8+
working_dir = 'test/data'
9+
10+
clone_cmd = [git2cpp_path, 'clone', url]
11+
subprocess.run(clone_cmd, capture_output=True, cwd = working_dir, text=True)
12+
13+
assert os.path.exists(working_dir + '/xtl')
14+
assert os.path.exists(working_dir + '/xtl/include')
15+
16+
cleanup_cmd = ['rm', '-rf', 'xtl']
17+
subprocess.run(cleanup_cmd, capture_output=True, cwd = working_dir, text=True)
18+

0 commit comments

Comments
 (0)