1
1
#include <iostream>
2
2
3
3
#include "../subcommand/clone_subcommand.hpp"
4
+ #include "../utils/output.hpp"
4
5
#include "../wrapper/repository_wrapper.hpp"
5
6
6
7
clone_subcommand::clone_subcommand(const libgit2_object&, CLI::App& app)
@@ -13,9 +14,90 @@ clone_subcommand::clone_subcommand(const libgit2_object&, CLI::App& app)
13
14
sub->callback([this]() { this->run(); });
14
15
}
15
16
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
+
16
88
void clone_subcommand::run()
17
89
{
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.payload = &pd;
100
+
19
101
std::string short_name = m_directory;
20
102
if (m_directory.empty())
21
103
{
@@ -27,5 +109,6 @@ void clone_subcommand::run()
27
109
m_directory = get_current_git_path() + '/' + short_name;
28
110
}
29
111
std::cout << "Cloning into '" + short_name + "'..." << std::endl;
30
- repository_wrapper::clone(m_repository, m_directory, opts);
112
+ cursor_hider ch;
113
+ repository_wrapper::clone(m_repository, m_directory, clone_opts);
31
114
}
0 commit comments