Skip to content

Commit 02924fe

Browse files
committed
Improved clone output
1 parent dbd11b0 commit 02924fe

File tree

3 files changed

+107
-2
lines changed

3 files changed

+107
-2
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ set(GIT2CPP_SRC
5555
${GIT2CPP_SOURCE_DIR}/utils/common.hpp
5656
${GIT2CPP_SOURCE_DIR}/utils/git_exception.cpp
5757
${GIT2CPP_SOURCE_DIR}/utils/git_exception.hpp
58+
${GIT2CPP_SOURCE_DIR}/utils/output.hpp
5859
${GIT2CPP_SOURCE_DIR}/wrapper/annotated_commit_wrapper.cpp
5960
${GIT2CPP_SOURCE_DIR}/wrapper/annotated_commit_wrapper.hpp
6061
${GIT2CPP_SOURCE_DIR}/wrapper/branch_wrapper.cpp

src/subcommand/clone_subcommand.cpp

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include <iostream>
22

33
#include "../subcommand/clone_subcommand.hpp"
4+
#include "../utils/output.hpp"
45
#include "../wrapper/repository_wrapper.hpp"
56

67
clone_subcommand::clone_subcommand(const libgit2_object&, CLI::App& app)
@@ -13,9 +14,91 @@ clone_subcommand::clone_subcommand(const libgit2_object&, CLI::App& app)
1314
sub->callback([this]() { this->run(); });
1415
}
1516

17+
namespace
18+
{
19+
int sideband_progress(const char* str, int len, void*)
20+
{
21+
printf("remote: %.*s", len, str);
22+
fflush(stdout);
23+
return 0;
24+
}
25+
26+
int fetch_progress(const git_indexer_progress* stats, void* payload)
27+
{
28+
static bool done = false;
29+
30+
// We need to copy stats into payload even if the fetch is done,
31+
// because the checkout_progress callback will be called with the
32+
// same payload and needs the data to be up do date.
33+
auto* pr = reinterpret_cast<git_indexer_progress*>(payload);
34+
*pr = *stats;
35+
36+
if (done)
37+
{
38+
return 0;
39+
}
40+
41+
int network_percent = pr->total_objects > 0 ?
42+
(100 * pr->received_objects / pr->total_objects)
43+
: 0;
44+
size_t mbytes = pr->received_bytes / (1024*1024);
45+
46+
std::cout << "Receiving objects: " << std::setw(4) << network_percent
47+
<< "% (" << pr->received_objects << "/" << pr->total_objects << "), "
48+
<< mbytes << " MiB";
49+
50+
if (pr->received_objects == pr->total_objects)
51+
{
52+
std::cout << ", done." << std::endl;
53+
done = true;
54+
}
55+
else
56+
{
57+
std::cout << '\r';
58+
}
59+
return 0;
60+
}
61+
62+
void checkout_progress(const char* path, size_t cur, size_t tot, void* payload)
63+
{
64+
static bool done = false;
65+
if (done)
66+
{
67+
return;
68+
}
69+
auto* pr = reinterpret_cast<git_indexer_progress*>(payload);
70+
int deltas_percent = pr->total_deltas > 0 ?
71+
(100 * pr->indexed_deltas / pr->total_deltas)
72+
: 0;
73+
74+
std::cout << "Resolving deltas: " << std::setw(4) << deltas_percent
75+
<< "% (" << pr->indexed_deltas << "/" << pr->total_deltas << ")";
76+
if (pr->indexed_deltas == pr->total_deltas)
77+
{
78+
std::cout << ", done." << std::endl;
79+
done = true;
80+
}
81+
else
82+
{
83+
std::cout << '\r';
84+
}
85+
}
86+
}
87+
1688
void clone_subcommand::run()
1789
{
18-
git_clone_options opts = GIT_CLONE_OPTIONS_INIT;
90+
git_indexer_progress pd;
91+
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
92+
git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
93+
checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
94+
checkout_opts.progress_cb = checkout_progress;
95+
checkout_opts.progress_payload = &pd;
96+
clone_opts.checkout_opts = checkout_opts;
97+
clone_opts.fetch_opts.callbacks.sideband_progress = sideband_progress;
98+
clone_opts.fetch_opts.callbacks.transfer_progress = fetch_progress;
99+
//clone_opts.fetch_opts.callbacks.credentials = cred_acquire_cb;
100+
clone_opts.fetch_opts.callbacks.payload = &pd;
101+
19102
std::string short_name = m_directory;
20103
if (m_directory.empty())
21104
{
@@ -27,5 +110,6 @@ void clone_subcommand::run()
27110
m_directory = get_current_git_path() + '/' + short_name;
28111
}
29112
std::cout << "Cloning into '" + short_name + "'..." << std::endl;
30-
repository_wrapper::clone(m_repository, m_directory, opts);
113+
cursor_hider ch;
114+
repository_wrapper::clone(m_repository, m_directory, clone_opts);
31115
}

src/utils/output.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pragma once
2+
3+
#include <iostream>
4+
#include "common.hpp"
5+
6+
// Scope object to hide the cursor. This avoids
7+
// cursor twinkling when rewritting the same line
8+
// too frequently.
9+
struct cursor_hider : noncopyable_nonmovable
10+
{
11+
cursor_hider()
12+
{
13+
std::cout << "\e[?25l";
14+
}
15+
16+
~cursor_hider()
17+
{
18+
std::cout << "\e[?25h";
19+
}
20+
};

0 commit comments

Comments
 (0)