1 module libgit2.example.clone;
2 
3 
4 private static import core.stdc.stdio;
5 private static import libgit2.checkout;
6 private static import libgit2.clone;
7 private static import libgit2.errors;
8 private static import libgit2.example.common;
9 private static import libgit2.indexer;
10 private static import libgit2.repository;
11 private static import libgit2.types;
12 
13 extern (C)
14 public struct progress_data
15 {
16 	libgit2.indexer.git_indexer_progress fetch_progress;
17 	size_t completed_steps;
18 	size_t total_steps;
19 	const (char)* path;
20 }
21 
22 extern (C)
23 nothrow @nogc
24 private void print_progress(const (.progress_data)* pd)
25 
26 	in
27 	{
28 	}
29 
30 	do
31 	{
32 		int network_percent = (pd.fetch_progress.total_objects > 0) ? ((100 * pd.fetch_progress.received_objects) / pd.fetch_progress.total_objects) : (0);
33 		int index_percent = (pd.fetch_progress.total_objects > 0) ? ((100 * pd.fetch_progress.indexed_objects) / pd.fetch_progress.total_objects) : (0);
34 
35 		int checkout_percent = (pd.total_steps > 0) ? (cast(int)((100 * pd.completed_steps) / pd.total_steps)) : (0);
36 		size_t kbytes = pd.fetch_progress.received_bytes / 1024;
37 
38 		if ((pd.fetch_progress.total_objects) && (pd.fetch_progress.received_objects == pd.fetch_progress.total_objects)) {
39 			core.stdc.stdio.printf("Resolving deltas %u/%u\r", pd.fetch_progress.indexed_deltas, pd.fetch_progress.total_deltas);
40 		} else {
41 			core.stdc.stdio.printf("net %3d%% (%4" ~ libgit2.example.common.PRIuZ ~ " kb, %5u/%5u)  /  idx %3d%% (%5u/%5u)  /  chk %3d%% (%4" ~ libgit2.example.common.PRIuZ ~ "/%4" ~ libgit2.example.common.PRIuZ ~ ")%s\n", network_percent, kbytes, pd.fetch_progress.received_objects, pd.fetch_progress.total_objects, index_percent, pd.fetch_progress.indexed_objects, pd.fetch_progress.total_objects, checkout_percent, pd.completed_steps, pd.total_steps, pd.path);
42 		}
43 	}
44 
45 extern (C)
46 nothrow @nogc
47 private int sideband_progress(const (char)* str, int len, void* payload)
48 
49 	in
50 	{
51 	}
52 
53 	do
54 	{
55 		//cast(void)(payload);
56 
57 		core.stdc.stdio.printf("remote: %.*s", len, str);
58 		core.stdc.stdio.fflush(core.stdc.stdio.stdout);
59 
60 		return 0;
61 	}
62 
63 extern (C)
64 nothrow @nogc
65 private int fetch_progress(const (libgit2.indexer.git_indexer_progress)* stats, void* payload)
66 
67 	in
68 	{
69 	}
70 
71 	do
72 	{
73 		.progress_data* pd = cast(.progress_data*)(payload);
74 		pd.fetch_progress = *stats;
75 		.print_progress(pd);
76 
77 		return 0;
78 	}
79 
80 extern (C)
81 nothrow @nogc
82 private void checkout_progress(const (char)* path, size_t cur, size_t tot, void* payload)
83 
84 	in
85 	{
86 	}
87 
88 	do
89 	{
90 		.progress_data* pd = cast(.progress_data*)(payload);
91 		pd.completed_steps = cur;
92 		pd.total_steps = tot;
93 		pd.path = path;
94 		.print_progress(pd);
95 	}
96 
97 extern (C)
98 nothrow @nogc
99 public int lg2_clone(libgit2.types.git_repository* repo, int argc, char** argv)
100 
101 	in
102 	{
103 	}
104 
105 	do
106 	{
107 		//cast(void)(repo);
108 		const (char)* url = argv[1];
109 		const (char)* path = argv[2];
110 
111 		/* Validate args */
112 		if (argc < 3) {
113 			core.stdc.stdio.printf("USAGE: %s <url> <path>\n", argv[0]);
114 
115 			return -1;
116 		}
117 
118 		/* Set up options */
119 		.progress_data pd = .progress_data.init;
120 		libgit2.checkout.git_checkout_options checkout_opts = libgit2.checkout.GIT_CHECKOUT_OPTIONS_INIT();
121 		checkout_opts.checkout_strategy = libgit2.checkout.git_checkout_strategy_t.GIT_CHECKOUT_SAFE;
122 		checkout_opts.progress_cb = &.checkout_progress;
123 		checkout_opts.progress_payload = &pd;
124 		libgit2.clone.git_clone_options clone_opts = libgit2.clone.GIT_CLONE_OPTIONS_INIT();
125 		clone_opts.checkout_opts = checkout_opts;
126 		clone_opts.fetch_opts.callbacks.sideband_progress = &.sideband_progress;
127 		clone_opts.fetch_opts.callbacks.transfer_progress = &.fetch_progress;
128 		clone_opts.fetch_opts.callbacks.credentials = &libgit2.example.common.cred_acquire_cb;
129 		clone_opts.fetch_opts.callbacks.payload = &pd;
130 
131 		/* Do the clone */
132 		libgit2.types.git_repository* cloned_repo = null;
133 		int error = libgit2.clone.git_clone(&cloned_repo, url, path, &clone_opts);
134 		core.stdc.stdio.printf("\n");
135 
136 		if (error != 0) {
137 			const (libgit2.errors.git_error)* err = libgit2.errors.git_error_last();
138 
139 			if (err != null) {
140 				core.stdc.stdio.printf("ERROR %d: %s\n", err.klass, err.message);
141 			} else {
142 				core.stdc.stdio.printf("ERROR %d: no detailed info\n", error);
143 			}
144 		} else if (cloned_repo != null) {
145 			libgit2.repository.git_repository_free(cloned_repo);
146 		}
147 
148 		return error;
149 	}