1 /*
2  * libgit2 "remote" example - shows how to modify remotes for a repo
3  *
4  * Written by the libgit2 contributors
5  *
6  * To the extent possible under law, the author(s) have dedicated all copyright
7  * and related and neighboring rights to this software to the public domain
8  * worldwide. This software is distributed without any warranty.
9  *
10  * You should have received a copy of the CC0 Public Domain Dedication along
11  * with this software. If not, see
12  * <http://creativecommons.org/publicdomain/zero/1.0/>.
13  */
14 module libgit2_d.example.remote;
15 
16 
17 private static import core.stdc.stdio;
18 private static import core.stdc.stdlib;
19 private static import core.stdc.string;
20 private static import libgit2_d.example.common;
21 private static import libgit2_d.remote;
22 private static import libgit2_d.strarray;
23 private static import libgit2_d.types;
24 
25 package:
26 
27 /**
28  * This is a sample program that is similar to "git remote".  See the
29  * documentation for that (try "git help remote") to understand what this
30  * program is emulating.
31  *
32  * This demonstrates using the libgit2 APIs to modify remotes of a repository.
33  */
34 
35 public enum subcmd
36 {
37 	subcmd_add,
38 	subcmd_remove,
39 	subcmd_rename,
40 	subcmd_seturl,
41 	subcmd_show,
42 }
43 
44 public struct remote_opts
45 {
46 	.subcmd cmd;
47 
48 	/* for command-specific args */
49 	int argc;
50 	char** argv;
51 }
52 
53 extern (C)
54 nothrow @nogc
55 //int lg2_remote(libgit2_d.types.git_repository* repo, int argc, char*[] argv)
56 public int lg2_remote(libgit2_d.types.git_repository* repo, int argc, char** argv)
57 
58 	in
59 	{
60 	}
61 
62 	do
63 	{
64 		int retval = 0;
65 		.remote_opts opt = .remote_opts.init;
66 
67 		.parse_subcmd(&opt, argc, argv);
68 
69 		switch (opt.cmd) {
70 			case .subcmd.subcmd_add:
71 				retval = .cmd_add(repo, &opt);
72 
73 				break;
74 
75 			case .subcmd.subcmd_remove:
76 				retval = .cmd_remove(repo, &opt);
77 
78 				break;
79 
80 			case .subcmd.subcmd_rename:
81 				retval = .cmd_rename(repo, &opt);
82 
83 				break;
84 
85 			case .subcmd.subcmd_seturl:
86 				retval = .cmd_seturl(repo, &opt);
87 
88 				break;
89 
90 			case .subcmd.subcmd_show:
91 				retval = .cmd_show(repo, &opt);
92 
93 				break;
94 
95 			default:
96 				break;
97 		}
98 
99 		return retval;
100 	}
101 
102 nothrow @nogc
103 private int cmd_add(libgit2_d.types.git_repository* repo, .remote_opts* o)
104 
105 	in
106 	{
107 	}
108 
109 	do
110 	{
111 		libgit2_d.types.git_remote* remote = null;
112 
113 		if (o.argc != 2) {
114 			.usage("you need to specify a name and URL", null);
115 		}
116 
117 		char* name = o.argv[0];
118 		char* url = o.argv[1];
119 
120 		libgit2_d.example.common.check_lg2(libgit2_d.remote.git_remote_create(&remote, repo, name, url), "could not create remote", null);
121 
122 		return 0;
123 	}
124 
125 nothrow @nogc
126 private int cmd_remove(libgit2_d.types.git_repository* repo, .remote_opts* o)
127 
128 	in
129 	{
130 	}
131 
132 	do
133 	{
134 		if (o.argc != 1) {
135 			.usage("you need to specify a name", null);
136 		}
137 
138 		char* name = o.argv[0];
139 
140 		libgit2_d.example.common.check_lg2(libgit2_d.remote.git_remote_delete(repo, name), "could not delete remote", name);
141 
142 		return 0;
143 	}
144 
145 nothrow @nogc
146 private int cmd_rename(libgit2_d.types.git_repository* repo, .remote_opts* o)
147 
148 	in
149 	{
150 	}
151 
152 	do
153 	{
154 		libgit2_d.strarray.git_strarray problems = libgit2_d.strarray.git_strarray.init;
155 
156 		if (o.argc != 2) {
157 			.usage("you need to specify old and new remote name", null);
158 		}
159 
160 		char* old = o.argv[0];
161 		char* new_ = o.argv[1];
162 
163 		int retval = libgit2_d.remote.git_remote_rename(&problems, repo, old, new_);
164 
165 		if (!retval) {
166 			return 0;
167 		}
168 
169 		for (int i = 0; i < cast(int)(problems.count); i++) {
170 			core.stdc.stdio.puts(problems.strings[0]);
171 		}
172 
173 		libgit2_d.strarray.git_strarray_free(&problems);
174 
175 		return retval;
176 	}
177 
178 nothrow @nogc
179 private int cmd_seturl(libgit2_d.types.git_repository* repo, .remote_opts* o)
180 
181 	in
182 	{
183 	}
184 
185 	do
186 	{
187 		int push = 0;
188 		char* name = null;
189 		char* url = null;
190 
191 		for (int i = 0; i < o.argc; i++) {
192 			char* arg = o.argv[i];
193 
194 			if (!core.stdc..string.strcmp(arg, "--push")) {
195 				push = 1;
196 			} else if ((arg[0] != '-') && (name == null)) {
197 				name = arg;
198 			} else if ((arg[0] != '-') && (url == null)) {
199 				url = arg;
200 			} else {
201 				.usage("invalid argument to set-url", arg);
202 			}
203 		}
204 
205 		if ((name == null) || (url == null)) {
206 			.usage("you need to specify remote and the new URL", null);
207 		}
208 
209 		int retval;
210 
211 		if (push) {
212 			retval = libgit2_d.remote.git_remote_set_pushurl(repo, name, url);
213 		} else {
214 			retval = libgit2_d.remote.git_remote_set_url(repo, name, url);
215 		}
216 
217 		libgit2_d.example.common.check_lg2(retval, "could not set URL", url);
218 
219 		return 0;
220 	}
221 
222 nothrow @nogc
223 private int cmd_show(libgit2_d.types.git_repository* repo, .remote_opts* o)
224 
225 	in
226 	{
227 	}
228 
229 	do
230 	{
231 		int verbose = 0;
232 		libgit2_d.strarray.git_strarray remotes = libgit2_d.strarray.git_strarray.init;
233 		libgit2_d.types.git_remote* remote = null;
234 
235 		for (int i = 0; i < o.argc; i++) {
236 			const (char)* arg = o.argv[i];
237 
238 			if ((!core.stdc..string.strcmp(arg, "-v")) || (!core.stdc..string.strcmp(arg, "--verbose"))) {
239 				verbose = 1;
240 			}
241 		}
242 
243 		libgit2_d.example.common.check_lg2(libgit2_d.remote.git_remote_list(&remotes, repo), "could not retrieve remotes", null);
244 
245 		for (int i = 0; i < cast(int)(remotes.count); i++) {
246 			const (char)* name = remotes.strings[i];
247 
248 			if (!verbose) {
249 				core.stdc.stdio.puts(name);
250 
251 				continue;
252 			}
253 
254 			libgit2_d.example.common.check_lg2(libgit2_d.remote.git_remote_lookup(&remote, repo, name), "could not look up remote", name);
255 
256 			const (char)* fetch = libgit2_d.remote.git_remote_url(remote);
257 
258 			if (fetch != null) {
259 				core.stdc.stdio.printf("%s\t%s (fetch)\n", name, fetch);
260 			}
261 
262 			const (char)* push = libgit2_d.remote.git_remote_pushurl(remote);
263 
264 			/* use fetch URL if no distinct push URL has been set */
265 			push = (push != null) ? (push) : (fetch);
266 
267 			if (push != null) {
268 				core.stdc.stdio.printf("%s\t%s (push)\n", name, push);
269 			}
270 
271 			libgit2_d.remote.git_remote_free(remote);
272 		}
273 
274 		libgit2_d.strarray.git_strarray_free(&remotes);
275 
276 		return 0;
277 	}
278 
279 nothrow @nogc
280 private void parse_subcmd(.remote_opts* opt, int argc, char** argv)
281 
282 	in
283 	{
284 	}
285 
286 	do
287 	{
288 		char* arg = argv[1];
289 		.subcmd cmd = cast(.subcmd)(0);
290 
291 		if (argc < 2) {
292 			.usage("no command specified", null);
293 		}
294 
295 		if (!core.stdc..string.strcmp(arg, "add")) {
296 			cmd = .subcmd.subcmd_add;
297 		} else if (!core.stdc..string.strcmp(arg, "remove")) {
298 			cmd = .subcmd.subcmd_remove;
299 		} else if (!core.stdc..string.strcmp(arg, "rename")) {
300 			cmd = .subcmd.subcmd_rename;
301 		} else if (!core.stdc..string.strcmp(arg, "set-url")) {
302 			cmd = .subcmd.subcmd_seturl;
303 		} else if (!core.stdc..string.strcmp(arg, "show")) {
304 			cmd = .subcmd.subcmd_show;
305 		} else {
306 			.usage("command is not valid", arg);
307 		}
308 
309 		opt.cmd = cmd;
310 
311 		/* executable and subcommand are removed */
312 		opt.argc = argc - 2;
313 
314 		opt.argv = argv + 2;
315 	}
316 
317 nothrow @nogc
318 private void usage(const (char)* msg, const (char)* arg)
319 
320 	in
321 	{
322 	}
323 
324 	do
325 	{
326 		core.stdc.stdio.fputs("usage: remote add <name> <url>\n", core.stdc.stdio.stderr);
327 		core.stdc.stdio.fputs("       remote remove <name>\n", core.stdc.stdio.stderr);
328 		core.stdc.stdio.fputs("       remote rename <old> <new>\n", core.stdc.stdio.stderr);
329 		core.stdc.stdio.fputs("       remote set-url [--push] <name> <newurl>\n", core.stdc.stdio.stderr);
330 		core.stdc.stdio.fputs("       remote show [-v|--verbose]\n", core.stdc.stdio.stderr);
331 
332 		if ((msg != null) && (arg == null)) {
333 			core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "\n%s\n", msg);
334 		} else if ((msg != null) && (arg != null)) {
335 			core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "\n%s: %s\n", msg, arg);
336 		}
337 
338 		core.stdc.stdlib.exit(1);
339 	}