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