]> git.ipfire.org Git - thirdparty/git.git/blame - builtin/rev-parse.c
Merge branch 'jk/bundle-use-dash-for-stdfiles'
[thirdparty/git.git] / builtin / rev-parse.c
CommitLineData
178cb243
LT
1/*
2 * rev-parse.c
3 *
4 * Copyright (C) Linus Torvalds, 2005
5 */
07047d68 6#define USE_THE_INDEX_VARIABLE
178cb243 7#include "cache.h"
36bf1958 8#include "alloc.h"
b2141fc1 9#include "config.h"
a8be83fe 10#include "commit.h"
41771fa4 11#include "hex.h"
960bba0d 12#include "refs.h"
c1babb1d 13#include "quote.h"
895f10c3 14#include "builtin.h"
21d47835 15#include "parse-options.h"
9dc01bf0
JH
16#include "diff.h"
17#include "revision.h"
a76295da 18#include "split-index.h"
bf0231c6 19#include "submodule.h"
64043556 20#include "commit-reach.h"
120ad2b0 21#include "shallow.h"
a8be83fe 22
4866ccf0
JH
23#define DO_REVS 1
24#define DO_NOREV 2
25#define DO_FLAGS 4
26#define DO_NONFLAGS 8
27static int filter = ~0;
28
96f1e58f 29static const char *def;
023d66ed 30
042a4ed7
LT
31#define NORMAL 0
32#define REVERSED 1
33static int show_type = NORMAL;
a6d97d49
JH
34
35#define SHOW_SYMBOLIC_ASIS 1
36#define SHOW_SYMBOLIC_FULL 2
96f1e58f
DR
37static int symbolic;
38static int abbrev;
a45d3469
BW
39static int abbrev_ref;
40static int abbrev_ref_strict;
96f1e58f 41static int output_sq;
4866ccf0 42
f8c87212 43static int stuck_long;
1e9f273a 44static struct ref_exclusions ref_excludes = REF_EXCLUSIONS_INIT;
f8c87212 45
921d865e
LT
46/*
47 * Some arguments are relevant "revision" arguments,
48 * others are about output format or other details.
49 * This sorts it all out.
50 */
51static int is_rev_argument(const char *arg)
52{
53 static const char *rev_args[] = {
e091eb93 54 "--all",
4866ccf0 55 "--bisect",
5a83f3be 56 "--dense",
b09fe971 57 "--branches=",
a62be77f 58 "--branches",
4866ccf0 59 "--header",
cc243c3c 60 "--ignore-missing",
921d865e 61 "--max-age=",
4866ccf0 62 "--max-count=",
4866ccf0 63 "--min-age=",
5ccfb758 64 "--no-merges",
ad5aeede
MG
65 "--min-parents=",
66 "--no-min-parents",
67 "--max-parents=",
68 "--no-max-parents",
4866ccf0 69 "--objects",
c6496575 70 "--objects-edge",
4866ccf0
JH
71 "--parents",
72 "--pretty",
b09fe971 73 "--remotes=",
a62be77f 74 "--remotes",
d08bae7e 75 "--glob=",
5a83f3be 76 "--sparse",
b09fe971 77 "--tags=",
a62be77f 78 "--tags",
4866ccf0 79 "--topo-order",
4c8725f1 80 "--date-order",
4866ccf0 81 "--unpacked",
921d865e
LT
82 NULL
83 };
84 const char **p = rev_args;
85
8233340c
EW
86 /* accept -<digit>, like traditional "head" */
87 if ((*arg == '-') && isdigit(arg[1]))
88 return 1;
89
921d865e
LT
90 for (;;) {
91 const char *str = *p++;
92 int len;
93 if (!str)
94 return 0;
95 len = strlen(str);
4866ccf0
JH
96 if (!strcmp(arg, str) ||
97 (str[len-1] == '=' && !strncmp(arg, str, len)))
921d865e
LT
98 return 1;
99 }
100}
101
4866ccf0 102/* Output argument as a string, either SQ or normal */
5bb2c65a
JH
103static void show(const char *arg)
104{
105 if (output_sq) {
106 int sq = '\'', ch;
107
108 putchar(sq);
109 while ((ch = *arg++)) {
110 if (ch == sq)
111 fputs("'\\'", stdout);
112 putchar(ch);
113 }
114 putchar(sq);
115 putchar(' ');
116 }
117 else
118 puts(arg);
119}
120
e00f3790
JS
121/* Like show(), but with a negation prefix according to type */
122static void show_with_type(int type, const char *arg)
123{
124 if (type != show_type)
125 putchar('^');
126 show(arg);
127}
128
4866ccf0 129/* Output a revision, only if filter allows it */
8bc095f7 130static void show_rev(int type, const struct object_id *oid, const char *name)
023d66ed 131{
4866ccf0 132 if (!(filter & DO_REVS))
023d66ed 133 return;
4866ccf0 134 def = NULL;
5bb2c65a 135
a45d3469
BW
136 if ((symbolic || abbrev_ref) && name) {
137 if (symbolic == SHOW_SYMBOLIC_FULL || abbrev_ref) {
8bc095f7 138 struct object_id discard;
a6d97d49
JH
139 char *full;
140
f24c30e0 141 switch (dwim_ref(name, strlen(name), &discard, &full, 0)) {
a6d97d49
JH
142 case 0:
143 /*
144 * Not found -- not a ref. We could
145 * emit "name" here, but symbolic-full
146 * users are interested in finding the
147 * refs spelled in full, and they would
148 * need to filter non-refs if we did so.
149 */
150 break;
151 case 1: /* happy */
a45d3469
BW
152 if (abbrev_ref)
153 full = shorten_unambiguous_ref(full,
154 abbrev_ref_strict);
e00f3790 155 show_with_type(type, full);
a6d97d49
JH
156 break;
157 default: /* ambiguous */
158 error("refname '%s' is ambiguous", name);
159 break;
160 }
28b35632 161 free(full);
a6d97d49 162 } else {
e00f3790 163 show_with_type(type, name);
a6d97d49
JH
164 }
165 }
d5012508 166 else if (abbrev)
aab9583f 167 show_with_type(type, find_unique_abbrev(oid, abbrev));
30b96fce 168 else
8bc095f7 169 show_with_type(type, oid_to_hex(oid));
023d66ed
LT
170}
171
4866ccf0 172/* Output a flag, only if filter allows it. */
16cee38a 173static int show_flag(const char *arg)
023d66ed 174{
4866ccf0 175 if (!(filter & DO_FLAGS))
9523a4c2
LT
176 return 0;
177 if (filter & (is_rev_argument(arg) ? DO_REVS : DO_NOREV)) {
0360e99d 178 show(arg);
9523a4c2
LT
179 return 1;
180 }
181 return 0;
023d66ed
LT
182}
183
dfd1b749 184static int show_default(void)
023d66ed 185{
16cee38a 186 const char *s = def;
023d66ed
LT
187
188 if (s) {
8bc095f7 189 struct object_id oid;
023d66ed
LT
190
191 def = NULL;
8bc095f7 192 if (!get_oid(s, &oid)) {
193 show_rev(NORMAL, &oid, s);
dfd1b749 194 return 1;
023d66ed 195 }
023d66ed 196 }
dfd1b749 197 return 0;
023d66ed
LT
198}
199
63e14ee2 200static int show_reference(const char *refname, const struct object_id *oid,
5cf88fd8 201 int flag UNUSED, void *cb_data UNUSED)
960bba0d 202{
1e9f273a 203 if (ref_excluded(&ref_excludes, refname))
9dc01bf0 204 return 0;
8bc095f7 205 show_rev(NORMAL, oid, refname);
960bba0d
LT
206 return 0;
207}
208
63e14ee2 209static int anti_reference(const char *refname, const struct object_id *oid,
5cf88fd8 210 int flag UNUSED, void *cb_data UNUSED)
ad3f9a71 211{
8bc095f7 212 show_rev(REVERSED, oid, refname);
ad3f9a71
LT
213 return 0;
214}
215
1b7ba794 216static int show_abbrev(const struct object_id *oid, void *cb_data)
957d7406 217{
8bc095f7 218 show_rev(NORMAL, oid, NULL);
957d7406
JH
219 return 0;
220}
221
c1babb1d
LT
222static void show_datestring(const char *flag, const char *datestr)
223{
5b1ef2ce 224 char *buffer;
c1babb1d
LT
225
226 /* date handling requires both flags and revs */
227 if ((filter & (DO_FLAGS | DO_REVS)) != (DO_FLAGS | DO_REVS))
228 return;
cb71f8bd 229 buffer = xstrfmt("%s%"PRItime, flag, approxidate(datestr));
c1babb1d 230 show(buffer);
5b1ef2ce 231 free(buffer);
c1babb1d
LT
232}
233
12b9d327 234static int show_file(const char *arg, int output_prefix)
7a3dd472 235{
7b34c2fa 236 show_default();
9ad0a933 237 if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) {
12b9d327
JK
238 if (output_prefix) {
239 const char *prefix = startup_info->prefix;
e4da43b1
JK
240 char *fname = prefix_filename(prefix, arg);
241 show(fname);
242 free(fname);
12b9d327
JK
243 } else
244 show(arg);
9ad0a933
LT
245 return 1;
246 }
247 return 0;
7a3dd472
LT
248}
249
b7d936b2 250static int try_difference(const char *arg)
3dd4e732
SB
251{
252 char *dotdot;
ae90bdce
BW
253 struct object_id start_oid;
254 struct object_id end_oid;
255 const char *end;
256 const char *start;
3dd4e732 257 int symmetric;
003c84f6 258 static const char head_by_default[] = "HEAD";
3dd4e732
SB
259
260 if (!(dotdot = strstr(arg, "..")))
261 return 0;
ae90bdce
BW
262 end = dotdot + 2;
263 start = arg;
264 symmetric = (*end == '.');
3dd4e732
SB
265
266 *dotdot = 0;
ae90bdce 267 end += symmetric;
3dd4e732 268
ae90bdce
BW
269 if (!*end)
270 end = head_by_default;
3dd4e732 271 if (dotdot == arg)
ae90bdce 272 start = head_by_default;
003c84f6 273
ae90bdce 274 if (start == head_by_default && end == head_by_default &&
003c84f6
JH
275 !symmetric) {
276 /*
277 * Just ".."? That is not a range but the
278 * pathspec for the parent directory.
279 */
280 *dotdot = '.';
281 return 0;
282 }
283
ae90bdce
BW
284 if (!get_oid_committish(start, &start_oid) && !get_oid_committish(end, &end_oid)) {
285 show_rev(NORMAL, &end_oid, end);
286 show_rev(symmetric ? NORMAL : REVERSED, &start_oid, start);
3dd4e732
SB
287 if (symmetric) {
288 struct commit_list *exclude;
289 struct commit *a, *b;
2122f675
SB
290 a = lookup_commit_reference(the_repository, &start_oid);
291 b = lookup_commit_reference(the_repository, &end_oid);
0ed556d3
EN
292 if (!a || !b) {
293 *dotdot = '.';
294 return 0;
295 }
2ce406cc 296 exclude = get_merge_bases(a, b);
3dd4e732 297 while (exclude) {
e510ab89 298 struct commit *commit = pop_commit(&exclude);
8bc095f7 299 show_rev(REVERSED, &commit->object.oid, NULL);
3dd4e732
SB
300 }
301 }
62f162f8 302 *dotdot = '.';
3dd4e732
SB
303 return 1;
304 }
305 *dotdot = '.';
306 return 0;
307}
308
2122f8b9
BS
309static int try_parent_shorthands(const char *arg)
310{
311 char *dotdot;
8bc095f7 312 struct object_id oid;
2122f8b9
BS
313 struct commit *commit;
314 struct commit_list *parents;
8779351d
VN
315 int parent_number;
316 int include_rev = 0;
317 int include_parents = 0;
318 int exclude_parent = 0;
319
320 if ((dotdot = strstr(arg, "^!"))) {
321 include_rev = 1;
322 if (dotdot[2])
323 return 0;
324 } else if ((dotdot = strstr(arg, "^@"))) {
325 include_parents = 1;
326 if (dotdot[2])
327 return 0;
328 } else if ((dotdot = strstr(arg, "^-"))) {
329 include_rev = 1;
330 exclude_parent = 1;
331
332 if (dotdot[2]) {
333 char *end;
334 exclude_parent = strtoul(dotdot + 2, &end, 10);
335 if (*end != '\0' || !exclude_parent)
336 return 0;
337 }
338 } else
2122f8b9
BS
339 return 0;
340
341 *dotdot = 0;
0ed556d3 342 if (get_oid_committish(arg, &oid) ||
2122f675 343 !(commit = lookup_commit_reference(the_repository, &oid))) {
62f162f8 344 *dotdot = '^';
2122f8b9 345 return 0;
62f162f8 346 }
2122f8b9 347
8779351d
VN
348 if (exclude_parent &&
349 exclude_parent > commit_list_count(commit->parents)) {
350 *dotdot = '^';
351 return 0;
352 }
353
354 if (include_rev)
8bc095f7 355 show_rev(NORMAL, &oid, arg);
8779351d
VN
356 for (parents = commit->parents, parent_number = 1;
357 parents;
358 parents = parents->next, parent_number++) {
a2e7b04c
JK
359 char *name = NULL;
360
8779351d
VN
361 if (exclude_parent && parent_number != exclude_parent)
362 continue;
363
a2e7b04c
JK
364 if (symbolic)
365 name = xstrfmt("%s^%d", arg, parent_number);
8779351d 366 show_rev(include_parents ? NORMAL : REVERSED,
8bc095f7 367 &parents->item->object.oid, name);
a2e7b04c 368 free(name);
8779351d 369 }
2122f8b9 370
62f162f8 371 *dotdot = '^';
2122f8b9
BS
372 return 1;
373}
374
21d47835
PH
375static int parseopt_dump(const struct option *o, const char *arg, int unset)
376{
377 struct strbuf *parsed = o->value;
378 if (unset)
379 strbuf_addf(parsed, " --no-%s", o->long_name);
f8c87212 380 else if (o->short_name && (o->long_name == NULL || !stuck_long))
21d47835
PH
381 strbuf_addf(parsed, " -%c", o->short_name);
382 else
383 strbuf_addf(parsed, " --%s", o->long_name);
384 if (arg) {
f8c87212
NV
385 if (!stuck_long)
386 strbuf_addch(parsed, ' ');
387 else if (o->long_name)
388 strbuf_addch(parsed, '=');
21d47835
PH
389 sq_quote_buf(parsed, arg);
390 }
391 return 0;
392}
393
394static const char *skipspaces(const char *s)
395{
396 while (isspace(*s))
397 s++;
398 return s;
399}
400
33e75122
BC
401static char *findspace(const char *s)
402{
403 for (; *s; s++)
404 if (isspace(*s))
405 return (char*)s;
406 return NULL;
407}
408
21d47835
PH
409static int cmd_parseopt(int argc, const char **argv, const char *prefix)
410{
6e0800ef 411 static int keep_dashdash = 0, stop_at_non_option = 0;
21d47835 412 static char const * const parseopt_usage[] = {
9c9b4f2f 413 N_("git rev-parse --parseopt [<options>] -- [<args>...]"),
21d47835
PH
414 NULL
415 };
416 static struct option parseopt_opts[] = {
d5d09d47 417 OPT_BOOL(0, "keep-dashdash", &keep_dashdash,
2c7c184c 418 N_("keep the `--` passed as an arg")),
d5d09d47 419 OPT_BOOL(0, "stop-at-non-option", &stop_at_non_option,
2c7c184c
NTND
420 N_("stop parsing after the "
421 "first non-option argument")),
f8c87212
NV
422 OPT_BOOL(0, "stuck-long", &stuck_long,
423 N_("output in stuck long form")),
21d47835
PH
424 OPT_END(),
425 };
2d893dff 426 static const char * const flag_chars = "*=?!";
21d47835 427
f285a2d7 428 struct strbuf sb = STRBUF_INIT, parsed = STRBUF_INIT;
21d47835
PH
429 const char **usage = NULL;
430 struct option *opts = NULL;
431 int onb = 0, osz = 0, unb = 0, usz = 0;
432
21d47835 433 strbuf_addstr(&parsed, "set --");
37782920 434 argc = parse_options(argc, argv, prefix, parseopt_opts, parseopt_usage,
21d47835
PH
435 PARSE_OPT_KEEP_DASHDASH);
436 if (argc < 1 || strcmp(argv[0], "--"))
437 usage_with_options(parseopt_usage, parseopt_opts);
438
21d47835
PH
439 /* get the usage up to the first line with a -- on it */
440 for (;;) {
72e37b6a 441 if (strbuf_getline(&sb, stdin) == EOF)
e2c59937 442 die(_("premature end of input"));
21d47835
PH
443 ALLOC_GROW(usage, unb + 1, usz);
444 if (!strcmp("--", sb.buf)) {
445 if (unb < 1)
e2c59937 446 die(_("no usage string given before the `--' separator"));
21d47835
PH
447 usage[unb] = NULL;
448 break;
449 }
450 usage[unb++] = strbuf_detach(&sb, NULL);
451 }
452
9bab5b60 453 /* parse: (<short>|<short>,<long>|<long>)[*=?!]*<arghint>? SP+ <help> */
72e37b6a 454 while (strbuf_getline(&sb, stdin) != EOF) {
21d47835 455 const char *s;
28a8d0f7 456 char *help;
21d47835
PH
457 struct option *o;
458
459 if (!sb.len)
460 continue;
461
462 ALLOC_GROW(opts, onb + 1, osz);
463 memset(opts + onb, 0, sizeof(opts[onb]));
464
465 o = &opts[onb++];
33e75122
BC
466 help = findspace(sb.buf);
467 if (!help || sb.buf == help) {
21d47835 468 o->type = OPTION_GROUP;
e1033436 469 o->help = xstrdup(skipspaces(sb.buf));
21d47835
PH
470 continue;
471 }
472
28a8d0f7
BC
473 *help = '\0';
474
21d47835 475 o->type = OPTION_CALLBACK;
28a8d0f7 476 o->help = xstrdup(skipspaces(help+1));
21d47835 477 o->value = &parsed;
ff962a3f 478 o->flags = PARSE_OPT_NOARG;
21d47835 479 o->callback = &parseopt_dump;
9bab5b60 480
2d893dff
IB
481 /* name(s) */
482 s = strpbrk(sb.buf, flag_chars);
afe8a907 483 if (!s)
2d893dff
IB
484 s = help;
485
f20b9c36
ØW
486 if (s == sb.buf)
487 die(_("missing opt-spec before option flags"));
488
2d893dff
IB
489 if (s - sb.buf == 1) /* short option only */
490 o->short_name = *sb.buf;
491 else if (sb.buf[1] != ',') /* long option only */
492 o->long_name = xmemdupz(sb.buf, s - sb.buf);
493 else {
494 o->short_name = *sb.buf;
495 o->long_name = xmemdupz(sb.buf + 2, s - sb.buf - 2);
496 }
497
498 /* flags */
499 while (s < help) {
500 switch (*s++) {
ff962a3f
PH
501 case '=':
502 o->flags &= ~PARSE_OPT_NOARG;
2d893dff 503 continue;
ff962a3f
PH
504 case '?':
505 o->flags &= ~PARSE_OPT_NOARG;
506 o->flags |= PARSE_OPT_OPTARG;
2d893dff 507 continue;
ff962a3f
PH
508 case '!':
509 o->flags |= PARSE_OPT_NONEG;
2d893dff 510 continue;
ff962a3f
PH
511 case '*':
512 o->flags |= PARSE_OPT_HIDDEN;
2d893dff 513 continue;
ff962a3f 514 }
2d893dff
IB
515 s--;
516 break;
21d47835
PH
517 }
518
2d893dff
IB
519 if (s < help)
520 o->argh = xmemdupz(s, help - s);
21d47835
PH
521 }
522 strbuf_release(&sb);
523
524 /* put an OPT_END() */
525 ALLOC_GROW(opts, onb + 1, osz);
526 memset(opts + onb, 0, sizeof(opts[onb]));
37782920 527 argc = parse_options(argc, argv, prefix, opts, usage,
29981380 528 (keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0) |
fcd91f8d 529 (stop_at_non_option ? PARSE_OPT_STOP_AT_NON_OPTION : 0) |
47e9cd28 530 PARSE_OPT_SHELL_EVAL);
21d47835 531
02962d36 532 strbuf_addstr(&parsed, " --");
e35f11c2 533 sq_quote_argv(&parsed, argv);
21d47835 534 puts(parsed.buf);
b6046abc 535 strbuf_release(&parsed);
21d47835
PH
536 return 0;
537}
538
50325377
CC
539static int cmd_sq_quote(int argc, const char **argv)
540{
541 struct strbuf buf = STRBUF_INIT;
542
543 if (argc)
e35f11c2 544 sq_quote_argv(&buf, argv);
50325377
CC
545 printf("%s\n", buf.buf);
546 strbuf_release(&buf);
547
548 return 0;
549}
550
b1b35969
CC
551static void die_no_single_rev(int quiet)
552{
553 if (quiet)
554 exit(1);
555 else
e2c59937 556 die(_("Needed a single revision"));
b1b35969
CC
557}
558
7006b5be 559static const char builtin_rev_parse_usage[] =
9c9b4f2f 560N_("git rev-parse --parseopt [<options>] -- [<args>...]\n"
2c7c184c 561 " or: git rev-parse --sq-quote [<arg>...]\n"
9c9b4f2f 562 " or: git rev-parse [<options>] [<arg>...]\n"
2c7c184c
NTND
563 "\n"
564 "Run \"git rev-parse --parseopt -h\" for more information on the first usage.");
7006b5be 565
9d16ca65
JK
566/*
567 * Parse "opt" or "opt=<value>", setting value respectively to either
568 * NULL or the string after "=".
569 */
570static int opt_with_value(const char *arg, const char *opt, const char **value)
571{
572 if (skip_prefix(arg, opt, &arg)) {
573 if (!*arg) {
574 *value = NULL;
575 return 1;
576 }
577 if (*arg++ == '=') {
578 *value = arg;
579 return 1;
580 }
581 }
582 return 0;
583}
584
ffddfc63
JK
585static void handle_ref_opt(const char *pattern, const char *prefix)
586{
587 if (pattern)
588 for_each_glob_ref_in(show_reference, pattern, prefix, NULL);
589 else
590 for_each_ref_in(prefix, show_reference, NULL);
1e9f273a 591 clear_ref_exclusions(&ref_excludes);
ffddfc63
JK
592}
593
fac60b89 594enum format_type {
595 /* We would like a relative path. */
596 FORMAT_RELATIVE,
597 /* We would like a canonical absolute path. */
598 FORMAT_CANONICAL,
599 /* We would like the default behavior. */
600 FORMAT_DEFAULT,
601};
602
603enum default_type {
604 /* Our default is a relative path. */
605 DEFAULT_RELATIVE,
606 /* Our default is a relative path if there's a shared root. */
607 DEFAULT_RELATIVE_IF_SHARED,
608 /* Our default is a canonical absolute path. */
609 DEFAULT_CANONICAL,
610 /* Our default is not to modify the item. */
611 DEFAULT_UNMODIFIED,
612};
613
614static void print_path(const char *path, const char *prefix, enum format_type format, enum default_type def)
615{
616 char *cwd = NULL;
617 /*
618 * We don't ever produce a relative path if prefix is NULL, so set the
619 * prefix to the current directory so that we can produce a relative
620 * path whenever possible. If we're using RELATIVE_IF_SHARED mode, then
621 * we want an absolute path unless the two share a common prefix, so don't
622 * set it in that case, since doing so causes a relative path to always
623 * be produced if possible.
624 */
625 if (!prefix && (format != FORMAT_DEFAULT || def != DEFAULT_RELATIVE_IF_SHARED))
626 prefix = cwd = xgetcwd();
627 if (format == FORMAT_DEFAULT && def == DEFAULT_UNMODIFIED) {
628 puts(path);
629 } else if (format == FORMAT_RELATIVE ||
630 (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE)) {
631 /*
632 * In order for relative_path to work as expected, we need to
633 * make sure that both paths are absolute paths. If we don't,
634 * we can end up with an unexpected absolute path that the user
635 * didn't want.
636 */
637 struct strbuf buf = STRBUF_INIT, realbuf = STRBUF_INIT, prefixbuf = STRBUF_INIT;
638 if (!is_absolute_path(path)) {
639 strbuf_realpath_forgiving(&realbuf, path, 1);
640 path = realbuf.buf;
641 }
642 if (!is_absolute_path(prefix)) {
643 strbuf_realpath_forgiving(&prefixbuf, prefix, 1);
644 prefix = prefixbuf.buf;
645 }
646 puts(relative_path(path, prefix, &buf));
647 strbuf_release(&buf);
648 strbuf_release(&realbuf);
649 strbuf_release(&prefixbuf);
650 } else if (format == FORMAT_DEFAULT && def == DEFAULT_RELATIVE_IF_SHARED) {
651 struct strbuf buf = STRBUF_INIT;
652 puts(relative_path(path, prefix, &buf));
653 strbuf_release(&buf);
654 } else {
655 struct strbuf buf = STRBUF_INIT;
656 strbuf_realpath_forgiving(&buf, path, 1);
657 puts(buf.buf);
658 strbuf_release(&buf);
659 }
660 free(cwd);
661}
662
a633fca0 663int cmd_rev_parse(int argc, const char **argv, const char *prefix)
178cb243 664{
dfd1b749 665 int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
fc7d47f0 666 int did_repo_setup = 0;
14185673 667 int has_dashdash = 0;
12b9d327 668 int output_prefix = 0;
8bc095f7 669 struct object_id oid;
c41a87dd 670 unsigned int flags = 0;
dfd1b749 671 const char *name = NULL;
c41a87dd 672 struct object_context unused;
098aa867 673 struct strbuf buf = STRBUF_INIT;
7e0d029f 674 const int hexsz = the_hash_algo->hexsz;
3a1f91cf 675 int seen_end_of_options = 0;
fac60b89 676 enum format_type format = FORMAT_DEFAULT;
a62be77f 677
21d47835
PH
678 if (argc > 1 && !strcmp("--parseopt", argv[1]))
679 return cmd_parseopt(argc - 1, argv + 1, prefix);
680
50325377
CC
681 if (argc > 1 && !strcmp("--sq-quote", argv[1]))
682 return cmd_sq_quote(argc - 2, argv + 2);
683
7006b5be
JN
684 if (argc > 1 && !strcmp("-h", argv[1]))
685 usage(builtin_rev_parse_usage);
686
14185673
JK
687 for (i = 1; i < argc; i++) {
688 if (!strcmp(argv[i], "--")) {
689 has_dashdash = 1;
690 break;
691 }
692 }
693
fc7d47f0
JK
694 /* No options; just report on whether we're in a git repo or not. */
695 if (argc == 1) {
696 setup_git_directory();
697 git_config(git_default_config, NULL);
698 return 0;
699 }
700
178cb243 701 for (i = 1; i < argc; i++) {
16cee38a 702 const char *arg = argv[i];
fb18a2ed 703
e05e2ae8
JK
704 if (as_is) {
705 if (show_file(arg, output_prefix) && as_is < 2)
706 verify_filename(prefix, arg, 0);
707 continue;
708 }
709
3a1f91cf
JK
710 if (!seen_end_of_options) {
711 if (!strcmp(arg, "--local-env-vars")) {
712 int i;
713 for (i = 0; local_repo_env[i]; i++)
714 printf("%s\n", local_repo_env[i]);
715 continue;
716 }
717 if (!strcmp(arg, "--resolve-git-dir")) {
718 const char *gitdir = argv[++i];
719 if (!gitdir)
e2c59937 720 die(_("--resolve-git-dir requires an argument"));
3a1f91cf
JK
721 gitdir = resolve_gitdir(gitdir);
722 if (!gitdir)
e2c59937 723 die(_("not a gitdir '%s'"), argv[i]);
3a1f91cf
JK
724 puts(gitdir);
725 continue;
726 }
fc7d47f0
JK
727 }
728
729 /* The rest of the options require a git repository. */
730 if (!did_repo_setup) {
731 prefix = setup_git_directory();
732 git_config(git_default_config, NULL);
733 did_repo_setup = 1;
124b05b2
DS
734
735 prepare_repo_settings(the_repository);
736 the_repository->settings.command_requires_full_index = 0;
fc7d47f0
JK
737 }
738
3a1f91cf
JK
739 if (!strcmp(arg, "--")) {
740 as_is = 2;
741 /* Pass on the "--" if we show anything but files.. */
742 if (filter & (DO_FLAGS | DO_REVS))
743 show_file(arg, 0);
744 continue;
745 }
746
747 if (!seen_end_of_options && *arg == '-') {
9033addf
JK
748 if (!strcmp(arg, "--git-path")) {
749 if (!argv[i + 1])
e2c59937 750 die(_("--git-path requires an argument"));
9033addf 751 strbuf_reset(&buf);
fac60b89 752 print_path(git_path("%s", argv[i + 1]), prefix,
753 format,
754 DEFAULT_RELATIVE_IF_SHARED);
9033addf
JK
755 i++;
756 continue;
757 }
758 if (!strcmp(arg,"-n")) {
759 if (++i >= argc)
e2c59937 760 die(_("-n requires an argument"));
9033addf
JK
761 if ((filter & DO_FLAGS) && (filter & DO_REVS)) {
762 show(arg);
763 show(argv[i]);
764 }
765 continue;
766 }
767 if (starts_with(arg, "-n")) {
768 if ((filter & DO_FLAGS) && (filter & DO_REVS))
769 show(arg);
770 continue;
771 }
fac60b89 772 if (opt_with_value(arg, "--path-format", &arg)) {
99fc5551 773 if (!arg)
e2c59937 774 die(_("--path-format requires an argument"));
fac60b89 775 if (!strcmp(arg, "absolute")) {
776 format = FORMAT_CANONICAL;
777 } else if (!strcmp(arg, "relative")) {
778 format = FORMAT_RELATIVE;
779 } else {
e2c59937 780 die(_("unknown argument to --path-format: %s"), arg);
fac60b89 781 }
782 continue;
783 }
178cb243 784 if (!strcmp(arg, "--default")) {
a43219f2
DS
785 def = argv[++i];
786 if (!def)
e2c59937 787 die(_("--default requires an argument"));
178cb243
LT
788 continue;
789 }
12b9d327 790 if (!strcmp(arg, "--prefix")) {
a43219f2
DS
791 prefix = argv[++i];
792 if (!prefix)
e2c59937 793 die(_("--prefix requires an argument"));
12b9d327
JK
794 startup_info->prefix = prefix;
795 output_prefix = 1;
12b9d327
JK
796 continue;
797 }
8ebb0184 798 if (!strcmp(arg, "--revs-only")) {
4866ccf0 799 filter &= ~DO_NOREV;
8ebb0184
LT
800 continue;
801 }
802 if (!strcmp(arg, "--no-revs")) {
4866ccf0 803 filter &= ~DO_REVS;
8ebb0184
LT
804 continue;
805 }
f79b65aa 806 if (!strcmp(arg, "--flags")) {
4866ccf0 807 filter &= ~DO_NONFLAGS;
f79b65aa
LT
808 continue;
809 }
810 if (!strcmp(arg, "--no-flags")) {
4866ccf0 811 filter &= ~DO_FLAGS;
f79b65aa
LT
812 continue;
813 }
023d66ed 814 if (!strcmp(arg, "--verify")) {
4866ccf0
JH
815 filter &= ~(DO_FLAGS|DO_NOREV);
816 verify = 1;
023d66ed 817 continue;
921d865e 818 }
b1b35969
CC
819 if (!strcmp(arg, "--quiet") || !strcmp(arg, "-q")) {
820 quiet = 1;
321c89bf 821 flags |= GET_OID_QUIETLY;
b1b35969
CC
822 continue;
823 }
9d16ca65 824 if (opt_with_value(arg, "--short", &arg)) {
d5012508
JH
825 filter &= ~(DO_FLAGS|DO_NOREV);
826 verify = 1;
827 abbrev = DEFAULT_ABBREV;
9d16ca65 828 if (!arg)
7b5b7721 829 continue;
9d16ca65 830 abbrev = strtoul(arg, NULL, 10);
1dc4fb84
JH
831 if (abbrev < MINIMUM_ABBREV)
832 abbrev = MINIMUM_ABBREV;
7e0d029f 833 else if (hexsz <= abbrev)
834 abbrev = hexsz;
d5012508
JH
835 continue;
836 }
5bb2c65a
JH
837 if (!strcmp(arg, "--sq")) {
838 output_sq = 1;
839 continue;
840 }
042a4ed7
LT
841 if (!strcmp(arg, "--not")) {
842 show_type ^= REVERSED;
843 continue;
844 }
30b96fce 845 if (!strcmp(arg, "--symbolic")) {
a6d97d49
JH
846 symbolic = SHOW_SYMBOLIC_ASIS;
847 continue;
848 }
849 if (!strcmp(arg, "--symbolic-full-name")) {
850 symbolic = SHOW_SYMBOLIC_FULL;
30b96fce
JH
851 continue;
852 }
9d16ca65 853 if (opt_with_value(arg, "--abbrev-ref", &arg)) {
a45d3469
BW
854 abbrev_ref = 1;
855 abbrev_ref_strict = warn_ambiguous_refs;
9d16ca65
JK
856 if (arg) {
857 if (!strcmp(arg, "strict"))
a45d3469 858 abbrev_ref_strict = 1;
9d16ca65 859 else if (!strcmp(arg, "loose"))
a45d3469
BW
860 abbrev_ref_strict = 0;
861 else
e2c59937 862 die(_("unknown mode for --abbrev-ref: %s"),
9d16ca65 863 arg);
a45d3469
BW
864 }
865 continue;
866 }
960bba0d 867 if (!strcmp(arg, "--all")) {
e23b0368 868 for_each_ref(show_reference, NULL);
1e9f273a 869 clear_ref_exclusions(&ref_excludes);
960bba0d
LT
870 continue;
871 }
ef87cc79
JK
872 if (skip_prefix(arg, "--disambiguate=", &arg)) {
873 for_each_abbrev(arg, show_abbrev, NULL);
957d7406
JH
874 continue;
875 }
ad3f9a71 876 if (!strcmp(arg, "--bisect")) {
67985e4e
JK
877 for_each_fullref_in("refs/bisect/bad", show_reference, NULL);
878 for_each_fullref_in("refs/bisect/good", anti_reference, NULL);
ad3f9a71
LT
879 continue;
880 }
ffddfc63 881 if (opt_with_value(arg, "--branches", &arg)) {
5ff36c9b
PS
882 if (ref_excludes.hidden_refs_configured)
883 return error(_("--exclude-hidden cannot be used together with --branches"));
ffddfc63 884 handle_ref_opt(arg, "refs/heads/");
a62be77f
SE
885 continue;
886 }
ffddfc63 887 if (opt_with_value(arg, "--tags", &arg)) {
5ff36c9b
PS
888 if (ref_excludes.hidden_refs_configured)
889 return error(_("--exclude-hidden cannot be used together with --tags"));
ffddfc63 890 handle_ref_opt(arg, "refs/tags/");
d08bae7e
IL
891 continue;
892 }
ef87cc79 893 if (skip_prefix(arg, "--glob=", &arg)) {
ffddfc63 894 handle_ref_opt(arg, NULL);
b09fe971
IL
895 continue;
896 }
ffddfc63 897 if (opt_with_value(arg, "--remotes", &arg)) {
5ff36c9b
PS
898 if (ref_excludes.hidden_refs_configured)
899 return error(_("--exclude-hidden cannot be used together with --remotes"));
ffddfc63 900 handle_ref_opt(arg, "refs/remotes/");
9dc01bf0
JH
901 continue;
902 }
ef87cc79
JK
903 if (skip_prefix(arg, "--exclude=", &arg)) {
904 add_ref_exclusion(&ref_excludes, arg);
a62be77f
SE
905 continue;
906 }
5ff36c9b
PS
907 if (skip_prefix(arg, "--exclude-hidden=", &arg)) {
908 exclude_hidden_refs(&ref_excludes, arg);
909 continue;
910 }
7cceca5c
SD
911 if (!strcmp(arg, "--show-toplevel")) {
912 const char *work_tree = get_git_work_tree();
913 if (work_tree)
fac60b89 914 print_path(work_tree, prefix, format, DEFAULT_UNMODIFIED);
2d92ab32 915 else
e2c59937 916 die(_("this operation must be run in a work tree"));
7cceca5c
SD
917 continue;
918 }
bf0231c6 919 if (!strcmp(arg, "--show-superproject-working-tree")) {
49d3c4b4
AM
920 struct strbuf superproject = STRBUF_INIT;
921 if (get_superproject_working_tree(&superproject))
fac60b89 922 print_path(superproject.buf, prefix, format, DEFAULT_UNMODIFIED);
49d3c4b4 923 strbuf_release(&superproject);
bf0231c6
SB
924 continue;
925 }
d288a700 926 if (!strcmp(arg, "--show-prefix")) {
4866ccf0
JH
927 if (prefix)
928 puts(prefix);
658219f1
RL
929 else
930 putchar('\n');
d288a700
LT
931 continue;
932 }
5f94c730
JH
933 if (!strcmp(arg, "--show-cdup")) {
934 const char *pfx = prefix;
e90fdc39
JS
935 if (!is_inside_work_tree()) {
936 const char *work_tree =
937 get_git_work_tree();
938 if (work_tree)
939 printf("%s\n", work_tree);
940 continue;
941 }
5f94c730
JH
942 while (pfx) {
943 pfx = strchr(pfx, '/');
944 if (pfx) {
945 pfx++;
946 printf("../");
947 }
948 }
949 putchar('\n');
950 continue;
951 }
a2f5a876
SG
952 if (!strcmp(arg, "--git-dir") ||
953 !strcmp(arg, "--absolute-git-dir")) {
a8783eeb 954 const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
56b9f6e7 955 char *cwd;
d06f15d9 956 int len;
fac60b89 957 enum format_type wanted = format;
a2f5a876
SG
958 if (arg[2] == 'g') { /* --git-dir */
959 if (gitdir) {
fac60b89 960 print_path(gitdir, prefix, format, DEFAULT_UNMODIFIED);
a2f5a876
SG
961 continue;
962 }
963 if (!prefix) {
fac60b89 964 print_path(".git", prefix, format, DEFAULT_UNMODIFIED);
a2f5a876
SG
965 continue;
966 }
967 } else { /* --absolute-git-dir */
fac60b89 968 wanted = FORMAT_CANONICAL;
a2f5a876
SG
969 if (!gitdir && !prefix)
970 gitdir = ".git";
971 if (gitdir) {
3d7747e3
AM
972 struct strbuf realpath = STRBUF_INIT;
973 strbuf_realpath(&realpath, gitdir, 1);
974 puts(realpath.buf);
975 strbuf_release(&realpath);
a2f5a876
SG
976 continue;
977 }
a8783eeb 978 }
56b9f6e7 979 cwd = xgetcwd();
d06f15d9 980 len = strlen(cwd);
fac60b89 981 strbuf_reset(&buf);
982 strbuf_addf(&buf, "%s%s.git", cwd, len && cwd[len-1] != '/' ? "/" : "");
56b9f6e7 983 free(cwd);
fac60b89 984 print_path(buf.buf, prefix, wanted, DEFAULT_CANONICAL);
a8783eeb
LT
985 continue;
986 }
31e26ebc 987 if (!strcmp(arg, "--git-common-dir")) {
fac60b89 988 print_path(get_git_common_dir(), prefix, format, DEFAULT_RELATIVE_IF_SHARED);
31e26ebc
NTND
989 continue;
990 }
6d9ba67b
JS
991 if (!strcmp(arg, "--is-inside-git-dir")) {
992 printf("%s\n", is_inside_git_dir() ? "true"
993 : "false");
994 continue;
995 }
892c41b9
ML
996 if (!strcmp(arg, "--is-inside-work-tree")) {
997 printf("%s\n", is_inside_work_tree() ? "true"
998 : "false");
999 continue;
1000 }
493c774e
ML
1001 if (!strcmp(arg, "--is-bare-repository")) {
1002 printf("%s\n", is_bare_repository() ? "true"
1003 : "false");
1004 continue;
1005 }
417abfde 1006 if (!strcmp(arg, "--is-shallow-repository")) {
c8813487
SB
1007 printf("%s\n",
1008 is_repository_shallow(the_repository) ? "true"
417abfde
ØW
1009 : "false");
1010 continue;
1011 }
a76295da 1012 if (!strcmp(arg, "--shared-index-path")) {
07047d68 1013 if (repo_read_index(the_repository) < 0)
a76295da
NTND
1014 die(_("Could not read the index"));
1015 if (the_index.split_index) {
2182abd9 1016 const struct object_id *oid = &the_index.split_index->base_oid;
1017 const char *path = git_path("sharedindex.%s", oid_to_hex(oid));
fac60b89 1018 print_path(path, prefix, format, DEFAULT_RELATIVE);
a76295da
NTND
1019 }
1020 continue;
1021 }
ef87cc79
JK
1022 if (skip_prefix(arg, "--since=", &arg)) {
1023 show_datestring("--max-age=", arg);
c1babb1d
LT
1024 continue;
1025 }
ef87cc79
JK
1026 if (skip_prefix(arg, "--after=", &arg)) {
1027 show_datestring("--max-age=", arg);
c1babb1d
LT
1028 continue;
1029 }
ef87cc79
JK
1030 if (skip_prefix(arg, "--before=", &arg)) {
1031 show_datestring("--min-age=", arg);
c1babb1d
LT
1032 continue;
1033 }
ef87cc79
JK
1034 if (skip_prefix(arg, "--until=", &arg)) {
1035 show_datestring("--min-age=", arg);
c1babb1d
LT
1036 continue;
1037 }
2eabd383 1038 if (opt_with_value(arg, "--show-object-format", &arg)) {
1039 const char *val = arg ? arg : "storage";
1040
1041 if (strcmp(val, "storage") &&
1042 strcmp(val, "input") &&
1043 strcmp(val, "output"))
e2c59937 1044 die(_("unknown mode for --show-object-format: %s"),
2eabd383 1045 arg);
1046 puts(the_hash_algo->name);
1047 continue;
1048 }
3a1f91cf
JK
1049 if (!strcmp(arg, "--end-of-options")) {
1050 seen_end_of_options = 1;
1051 if (filter & (DO_FLAGS | DO_REVS))
1052 show_file(arg, 0);
1053 continue;
1054 }
9523a4c2 1055 if (show_flag(arg) && verify)
b1b35969 1056 die_no_single_rev(quiet);
178cb243
LT
1057 continue;
1058 }
4866ccf0
JH
1059
1060 /* Not a flag argument */
3dd4e732
SB
1061 if (try_difference(arg))
1062 continue;
2122f8b9
BS
1063 if (try_parent_shorthands(arg))
1064 continue;
dfd1b749
CC
1065 name = arg;
1066 type = NORMAL;
1067 if (*arg == '^') {
1068 name++;
1069 type = REVERSED;
800644c5 1070 }
3a7a698e
NTND
1071 if (!get_oid_with_context(the_repository, name,
1072 flags, &oid, &unused)) {
dfd1b749
CC
1073 if (verify)
1074 revs_count++;
1075 else
8bc095f7 1076 show_rev(type, &oid, name);
800644c5
LT
1077 continue;
1078 }
75ecfce3
CC
1079 if (verify)
1080 die_no_single_rev(quiet);
14185673 1081 if (has_dashdash)
e2c59937 1082 die(_("bad revision '%s'"), arg);
9ad0a933 1083 as_is = 1;
12b9d327 1084 if (!show_file(arg, output_prefix))
9ad0a933 1085 continue;
023e37c3 1086 verify_filename(prefix, arg, 1);
023d66ed 1087 }
098aa867 1088 strbuf_release(&buf);
dfd1b749
CC
1089 if (verify) {
1090 if (revs_count == 1) {
8bc095f7 1091 show_rev(type, &oid, name);
dfd1b749
CC
1092 return 0;
1093 } else if (revs_count == 0 && show_default())
1094 return 0;
b1b35969 1095 die_no_single_rev(quiet);
dfd1b749
CC
1096 } else
1097 show_default();
178cb243
LT
1098 return 0;
1099}