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 //Declaration name in C language
45 public enum
46 {
47 	subcmd_add = .subcmd.subcmd_add,
48 	subcmd_remove = .subcmd.subcmd_remove,
49 	subcmd_rename = .subcmd.subcmd_rename,
50 	subcmd_seturl = .subcmd.subcmd_seturl,
51 	subcmd_show = .subcmd.subcmd_show,
52 }
53 
54 public struct remote_opts
55 {
56 	.subcmd cmd;
57 
58 	/* for command-specific args */
59 	int argc;
60 	char** argv;
61 }
62 
63 extern (C)
64 nothrow @nogc
65 //int lg2_remote(libgit2_d.types.git_repository* repo, int argc, char*[] argv)
66 public int lg2_remote(libgit2_d.types.git_repository* repo, int argc, char** argv)
67 
68 	in
69 	{
70 	}
71 
72 	do
73 	{
74 		int retval = 0;
75 		.remote_opts opt = .remote_opts.init;
76 
77 		.parse_subcmd(&opt, argc, argv);
78 
79 		switch (opt.cmd) {
80 			case .subcmd.subcmd_add:
81 				retval = .cmd_add(repo, &opt);
82 
83 				break;
84 
85 			case .subcmd.subcmd_remove:
86 				retval = .cmd_remove(repo, &opt);
87 
88 				break;
89 
90 			case .subcmd.subcmd_rename:
91 				retval = .cmd_rename(repo, &opt);
92 
93 				break;
94 
95 			case .subcmd.subcmd_seturl:
96 				retval = .cmd_seturl(repo, &opt);
97 
98 				break;
99 
100 			case .subcmd.subcmd_show:
101 				retval = .cmd_show(repo, &opt);
102 
103 				break;
104 
105 			default:
106 				break;
107 		}
108 
109 		return retval;
110 	}
111 
112 nothrow @nogc
113 private int cmd_add(libgit2_d.types.git_repository* repo, .remote_opts* o)
114 
115 	in
116 	{
117 	}
118 
119 	do
120 	{
121 		libgit2_d.types.git_remote* remote = null;
122 
123 		if (o.argc != 2) {
124 			.usage("you need to specify a name and URL", null);
125 		}
126 
127 		char* name = o.argv[0];
128 		char* url = o.argv[1];
129 
130 		libgit2_d.example.common.check_lg2(libgit2_d.remote.git_remote_create(&remote, repo, name, url), "could not create remote", null);
131 
132 		return 0;
133 	}
134 
135 nothrow @nogc
136 private int cmd_remove(libgit2_d.types.git_repository* repo, .remote_opts* o)
137 
138 	in
139 	{
140 	}
141 
142 	do
143 	{
144 		if (o.argc != 1) {
145 			.usage("you need to specify a name", null);
146 		}
147 
148 		char* name = o.argv[0];
149 
150 		libgit2_d.example.common.check_lg2(libgit2_d.remote.git_remote_delete(repo, name), "could not delete remote", name);
151 
152 		return 0;
153 	}
154 
155 nothrow @nogc
156 private int cmd_rename(libgit2_d.types.git_repository* repo, .remote_opts* o)
157 
158 	in
159 	{
160 	}
161 
162 	do
163 	{
164 		libgit2_d.strarray.git_strarray problems = libgit2_d.strarray.git_strarray.init;
165 
166 		if (o.argc != 2) {
167 			.usage("you need to specify old and new remote name", null);
168 		}
169 
170 		char* old = o.argv[0];
171 		char* new_ = o.argv[1];
172 
173 		int retval = libgit2_d.remote.git_remote_rename(&problems, repo, old, new_);
174 
175 		if (!retval) {
176 			return 0;
177 		}
178 
179 		for (int i = 0; i < cast(int)(problems.count); i++) {
180 			core.stdc.stdio.puts(problems.strings[0]);
181 		}
182 
183 		libgit2_d.strarray.git_strarray_dispose(&problems);
184 
185 		return retval;
186 	}
187 
188 nothrow @nogc
189 private int cmd_seturl(libgit2_d.types.git_repository* repo, .remote_opts* o)
190 
191 	in
192 	{
193 	}
194 
195 	do
196 	{
197 		int push = 0;
198 		char* name = null;
199 		char* url = null;
200 
201 		for (int i = 0; i < o.argc; i++) {
202 			char* arg = o.argv[i];
203 
204 			if (!core.stdc..string.strcmp(arg, "--push")) {
205 				push = 1;
206 			} else if ((arg[0] != '-') && (name == null)) {
207 				name = arg;
208 			} else if ((arg[0] != '-') && (url == null)) {
209 				url = arg;
210 			} else {
211 				.usage("invalid argument to set-url", arg);
212 			}
213 		}
214 
215 		if ((name == null) || (url == null)) {
216 			.usage("you need to specify remote and the new URL", null);
217 		}
218 
219 		int retval;
220 
221 		if (push) {
222 			retval = libgit2_d.remote.git_remote_set_pushurl(repo, name, url);
223 		} else {
224 			retval = libgit2_d.remote.git_remote_set_url(repo, name, url);
225 		}
226 
227 		libgit2_d.example.common.check_lg2(retval, "could not set URL", url);
228 
229 		return 0;
230 	}
231 
232 nothrow @nogc
233 private int cmd_show(libgit2_d.types.git_repository* repo, .remote_opts* o)
234 
235 	in
236 	{
237 	}
238 
239 	do
240 	{
241 		int verbose = 0;
242 		libgit2_d.strarray.git_strarray remotes = libgit2_d.strarray.git_strarray.init;
243 		libgit2_d.types.git_remote* remote = null;
244 
245 		for (int i = 0; i < o.argc; i++) {
246 			const (char)* arg = o.argv[i];
247 
248 			if ((!core.stdc..string.strcmp(arg, "-v")) || (!core.stdc..string.strcmp(arg, "--verbose"))) {
249 				verbose = 1;
250 			}
251 		}
252 
253 		libgit2_d.example.common.check_lg2(libgit2_d.remote.git_remote_list(&remotes, repo), "could not retrieve remotes", null);
254 
255 		for (int i = 0; i < cast(int)(remotes.count); i++) {
256 			const (char)* name = remotes.strings[i];
257 
258 			if (!verbose) {
259 				core.stdc.stdio.puts(name);
260 
261 				continue;
262 			}
263 
264 			libgit2_d.example.common.check_lg2(libgit2_d.remote.git_remote_lookup(&remote, repo, name), "could not look up remote", name);
265 
266 			const (char)* fetch = libgit2_d.remote.git_remote_url(remote);
267 
268 			if (fetch != null) {
269 				core.stdc.stdio.printf("%s\t%s (fetch)\n", name, fetch);
270 			}
271 
272 			const (char)* push = libgit2_d.remote.git_remote_pushurl(remote);
273 
274 			/* use fetch URL if no distinct push URL has been set */
275 			push = (push != null) ? (push) : (fetch);
276 
277 			if (push != null) {
278 				core.stdc.stdio.printf("%s\t%s (push)\n", name, push);
279 			}
280 
281 			libgit2_d.remote.git_remote_free(remote);
282 		}
283 
284 		libgit2_d.strarray.git_strarray_dispose(&remotes);
285 
286 		return 0;
287 	}
288 
289 nothrow @nogc
290 private void parse_subcmd(.remote_opts* opt, int argc, char** argv)
291 
292 	in
293 	{
294 	}
295 
296 	do
297 	{
298 		char* arg = argv[1];
299 		.subcmd cmd = cast(.subcmd)(0);
300 
301 		if (argc < 2) {
302 			.usage("no command specified", null);
303 		}
304 
305 		if (!core.stdc..string.strcmp(arg, "add")) {
306 			cmd = .subcmd.subcmd_add;
307 		} else if (!core.stdc..string.strcmp(arg, "remove")) {
308 			cmd = .subcmd.subcmd_remove;
309 		} else if (!core.stdc..string.strcmp(arg, "rename")) {
310 			cmd = .subcmd.subcmd_rename;
311 		} else if (!core.stdc..string.strcmp(arg, "set-url")) {
312 			cmd = .subcmd.subcmd_seturl;
313 		} else if (!core.stdc..string.strcmp(arg, "show")) {
314 			cmd = .subcmd.subcmd_show;
315 		} else {
316 			.usage("command is not valid", arg);
317 		}
318 
319 		opt.cmd = cmd;
320 
321 		/* executable and subcommand are removed */
322 		opt.argc = argc - 2;
323 
324 		opt.argv = argv + 2;
325 	}
326 
327 nothrow @nogc
328 private void usage(const (char)* msg, const (char)* arg)
329 
330 	in
331 	{
332 	}
333 
334 	do
335 	{
336 		core.stdc.stdio.fputs("usage: remote add <name> <url>\n", core.stdc.stdio.stderr);
337 		core.stdc.stdio.fputs("       remote remove <name>\n", core.stdc.stdio.stderr);
338 		core.stdc.stdio.fputs("       remote rename <old> <new>\n", core.stdc.stdio.stderr);
339 		core.stdc.stdio.fputs("       remote set-url [--push] <name> <newurl>\n", core.stdc.stdio.stderr);
340 		core.stdc.stdio.fputs("       remote show [-v|--verbose]\n", core.stdc.stdio.stderr);
341 
342 		if ((msg != null) && (arg == null)) {
343 			core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "\n%s\n", msg);
344 		} else if ((msg != null) && (arg != null)) {
345 			core.stdc.stdio.fprintf(core.stdc.stdio.stderr, "\n%s: %s\n", msg, arg);
346 		}
347 
348 		core.stdc.stdlib.exit(1);
349 	}