11#include < iostream>
22
33#include " ../subcommand/clone_subcommand.hpp"
4+ #include " ../utils/output.hpp"
45#include " ../wrapper/repository_wrapper.hpp"
56
67clone_subcommand::clone_subcommand (const libgit2_object&, CLI::App& app)
@@ -13,9 +14,90 @@ 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+
1688void 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 .payload = &pd;
100+
19101 std::string short_name = m_directory;
20102 if (m_directory.empty ())
21103 {
@@ -27,5 +109,6 @@ void clone_subcommand::run()
27109 m_directory = get_current_git_path () + ' /' + short_name;
28110 }
29111 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);
31114}
0 commit comments