rev-parse: let some options run outside repository

Once upon a time, you could use "--local-env-vars" and "--resolve-git-dir" outside of any git repository, but they had to come first on the command line. Commit 68889b4 (rev-parse: remove restrictions on some options, 2013-07-21) put them into the normal option-parsing loop, fixing the latter. But it inadvertently broke the former, as we call setup_git_directory() before starting that loop. We can note that those options don't care even conditionally about whether we are in a git repo. So it's fine if we simply wait to setup the repo until we see an option that needs it. However, there is one special exception we should make: historically, rev-parse will set up the repository and read config even if there are _no_ options. Some of the tests in t1300 rely on this to check "git -c $config" parsing. That's not mirroring real-world use, and we could tweak the test. But t0002 uses a bare "git rev-parse" to check "are we in a git repository?". It's plausible that real-world scripts are relying on this. So let's cover this case specially, and treat an option-less "rev-parse" as "see if we're in a repo". Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Feb 29, 2016 at 06:01 UTC fc7d47f0dd4f041af2ed2004700f18b635f3b204
2 files changed +34 -20
builtin/rev-parse.c
+32 -18
@@ -505,6 +505,7 @@ N_("git rev-parse --parseopt [<options>] -- [<args>...]\n"
505 int cmd_rev_parse(int argc, const char **argv, const char *prefix)
506 {
507 int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
508 + int did_repo_setup = 0;
509 int has_dashdash = 0;
510 int output_prefix = 0;
511 unsigned char sha1[20];
@@ -528,11 +529,40 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
529 }
530 }
531
531 - prefix = setup_git_directory();
532 - git_config(git_default_config, NULL);
532 + /* No options; just report on whether we're in a git repo or not. */
533 + if (argc == 1) {
534 + setup_git_directory();
535 + git_config(git_default_config, NULL);
536 + return 0;
537 + }
538 +
539 for (i = 1; i < argc; i++) {
540 const char *arg = argv[i];
541
542 + if (!strcmp(arg, "--local-env-vars")) {
543 + int i;
544 + for (i = 0; local_repo_env[i]; i++)
545 + printf("%s\n", local_repo_env[i]);
546 + continue;
547 + }
548 + if (!strcmp(arg, "--resolve-git-dir")) {
549 + const char *gitdir = argv[++i];
550 + if (!gitdir)
551 + die("--resolve-git-dir requires an argument");
552 + gitdir = resolve_gitdir(gitdir);
553 + if (!gitdir)
554 + die("not a gitdir '%s'", argv[i]);
555 + puts(gitdir);
556 + continue;
557 + }
558 +
559 + /* The rest of the options require a git repository. */
560 + if (!did_repo_setup) {
561 + prefix = setup_git_directory();
562 + git_config(git_default_config, NULL);
563 + did_repo_setup = 1;
564 + }
565 +
566 if (!strcmp(arg, "--git-path")) {
567 if (!argv[i + 1])
568 die("--git-path requires an argument");
@@ -706,12 +736,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
736 add_ref_exclusion(&ref_excludes, arg + 10);
737 continue;
738 }
709 - if (!strcmp(arg, "--local-env-vars")) {
710 - int i;
711 - for (i = 0; local_repo_env[i]; i++)
712 - printf("%s\n", local_repo_env[i]);
713 - continue;
714 - }
739 if (!strcmp(arg, "--show-toplevel")) {
740 const char *work_tree = get_git_work_tree();
741 if (work_tree)
@@ -766,16 +790,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
790 puts(get_git_common_dir());
791 continue;
792 }
769 - if (!strcmp(arg, "--resolve-git-dir")) {
770 - const char *gitdir = argv[++i];
771 - if (!gitdir)
772 - die("--resolve-git-dir requires an argument");
773 - gitdir = resolve_gitdir(gitdir);
774 - if (!gitdir)
775 - die("not a gitdir '%s'", argv[i]);
776 - puts(gitdir);
777 - continue;
778 - }
793 if (!strcmp(arg, "--is-inside-git-dir")) {
794 printf("%s\n", is_inside_git_dir() ? "true"
795 : "false");
t/t1515-rev-parse-outside-repo.sh
+2 -2
@@ -27,14 +27,14 @@ test_expect_success 'rev-parse --sq-quote' '
27 test_cmp expect actual
28 '
29
30 -test_expect_failure 'rev-parse --local-env-vars' '
30 +test_expect_success 'rev-parse --local-env-vars' '
31 git rev-parse --local-env-vars >actual &&
32 # we do not want to depend on the complete list here,
33 # so just look for something plausible
34 grep ^GIT_DIR actual
35 '
36
37 -test_expect_failure 'rev-parse --resolve-git-dir' '
37 +test_expect_success 'rev-parse --resolve-git-dir' '
38 git init --separate-git-dir repo dir &&
39 test_must_fail git rev-parse --resolve-git-dir . &&
40 echo "$(pwd)/repo" >expect &&