|
8 | 8 | #include "refs.h"
|
9 | 9 | #include "quote.h"
|
10 | 10 | #include "builtin.h"
|
| 11 | +#include "parse-options.h" |
11 | 12 |
|
12 | 13 | #define DO_REVS 1
|
13 | 14 | #define DO_NOREV 2
|
@@ -209,13 +210,138 @@ static int try_difference(const char *arg)
|
209 | 210 | return 0;
|
210 | 211 | }
|
211 | 212 |
|
| 213 | +static int parseopt_dump(const struct option *o, const char *arg, int unset) |
| 214 | +{ |
| 215 | + struct strbuf *parsed = o->value; |
| 216 | + if (unset) |
| 217 | + strbuf_addf(parsed, " --no-%s", o->long_name); |
| 218 | + else if (o->short_name) |
| 219 | + strbuf_addf(parsed, " -%c", o->short_name); |
| 220 | + else |
| 221 | + strbuf_addf(parsed, " --%s", o->long_name); |
| 222 | + if (arg) { |
| 223 | + strbuf_addch(parsed, ' '); |
| 224 | + sq_quote_buf(parsed, arg); |
| 225 | + } |
| 226 | + return 0; |
| 227 | +} |
| 228 | + |
| 229 | +static const char *skipspaces(const char *s) |
| 230 | +{ |
| 231 | + while (isspace(*s)) |
| 232 | + s++; |
| 233 | + return s; |
| 234 | +} |
| 235 | + |
| 236 | +static int cmd_parseopt(int argc, const char **argv, const char *prefix) |
| 237 | +{ |
| 238 | + static int keep_dashdash = 0; |
| 239 | + static char const * const parseopt_usage[] = { |
| 240 | + "git-rev-parse --parseopt [options] -- [<args>...]", |
| 241 | + NULL |
| 242 | + }; |
| 243 | + static struct option parseopt_opts[] = { |
| 244 | + OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash, |
| 245 | + "keep the `--` passed as an arg"), |
| 246 | + OPT_END(), |
| 247 | + }; |
| 248 | + |
| 249 | + struct strbuf sb, parsed; |
| 250 | + const char **usage = NULL; |
| 251 | + struct option *opts = NULL; |
| 252 | + int onb = 0, osz = 0, unb = 0, usz = 0; |
| 253 | + |
| 254 | + strbuf_init(&parsed, 0); |
| 255 | + strbuf_addstr(&parsed, "set --"); |
| 256 | + argc = parse_options(argc, argv, parseopt_opts, parseopt_usage, |
| 257 | + PARSE_OPT_KEEP_DASHDASH); |
| 258 | + if (argc < 1 || strcmp(argv[0], "--")) |
| 259 | + usage_with_options(parseopt_usage, parseopt_opts); |
| 260 | + |
| 261 | + strbuf_init(&sb, 0); |
| 262 | + /* get the usage up to the first line with a -- on it */ |
| 263 | + for (;;) { |
| 264 | + if (strbuf_getline(&sb, stdin, '\n') == EOF) |
| 265 | + die("premature end of input"); |
| 266 | + ALLOC_GROW(usage, unb + 1, usz); |
| 267 | + if (!strcmp("--", sb.buf)) { |
| 268 | + if (unb < 1) |
| 269 | + die("no usage string given before the `--' separator"); |
| 270 | + usage[unb] = NULL; |
| 271 | + break; |
| 272 | + } |
| 273 | + usage[unb++] = strbuf_detach(&sb, NULL); |
| 274 | + } |
| 275 | + |
| 276 | + /* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */ |
| 277 | + while (strbuf_getline(&sb, stdin, '\n') != EOF) { |
| 278 | + const char *s; |
| 279 | + struct option *o; |
| 280 | + |
| 281 | + if (!sb.len) |
| 282 | + continue; |
| 283 | + |
| 284 | + ALLOC_GROW(opts, onb + 1, osz); |
| 285 | + memset(opts + onb, 0, sizeof(opts[onb])); |
| 286 | + |
| 287 | + o = &opts[onb++]; |
| 288 | + s = strchr(sb.buf, ' '); |
| 289 | + if (!s || *sb.buf == ' ') { |
| 290 | + o->type = OPTION_GROUP; |
| 291 | + o->help = xstrdup(skipspaces(s)); |
| 292 | + continue; |
| 293 | + } |
| 294 | + |
| 295 | + o->type = OPTION_CALLBACK; |
| 296 | + o->help = xstrdup(skipspaces(s)); |
| 297 | + o->value = &parsed; |
| 298 | + o->callback = &parseopt_dump; |
| 299 | + switch (s[-1]) { |
| 300 | + case '=': |
| 301 | + s--; |
| 302 | + break; |
| 303 | + case '?': |
| 304 | + o->flags = PARSE_OPT_OPTARG; |
| 305 | + s--; |
| 306 | + break; |
| 307 | + default: |
| 308 | + o->flags = PARSE_OPT_NOARG; |
| 309 | + break; |
| 310 | + } |
| 311 | + |
| 312 | + if (s - sb.buf == 1) /* short option only */ |
| 313 | + o->short_name = *sb.buf; |
| 314 | + else if (sb.buf[1] != ',') /* long option only */ |
| 315 | + o->long_name = xmemdupz(sb.buf, s - sb.buf); |
| 316 | + else { |
| 317 | + o->short_name = *sb.buf; |
| 318 | + o->long_name = xmemdupz(sb.buf + 2, s - sb.buf - 2); |
| 319 | + } |
| 320 | + } |
| 321 | + strbuf_release(&sb); |
| 322 | + |
| 323 | + /* put an OPT_END() */ |
| 324 | + ALLOC_GROW(opts, onb + 1, osz); |
| 325 | + memset(opts + onb, 0, sizeof(opts[onb])); |
| 326 | + argc = parse_options(argc, argv, opts, usage, |
| 327 | + keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0); |
| 328 | + |
| 329 | + strbuf_addf(&parsed, " --"); |
| 330 | + sq_quote_argv(&parsed, argv, argc, 0); |
| 331 | + puts(parsed.buf); |
| 332 | + return 0; |
| 333 | +} |
| 334 | + |
212 | 335 | int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
213 | 336 | {
|
214 | 337 | int i, as_is = 0, verify = 0;
|
215 | 338 | unsigned char sha1[20];
|
216 | 339 |
|
217 | 340 | git_config(git_default_config);
|
218 | 341 |
|
| 342 | + if (argc > 1 && !strcmp("--parseopt", argv[1])) |
| 343 | + return cmd_parseopt(argc - 1, argv + 1, prefix); |
| 344 | + |
219 | 345 | for (i = 1; i < argc; i++) {
|
220 | 346 | const char *arg = argv[i];
|
221 | 347 |
|
|
0 commit comments