refs: make rev-parse --quiet actually quiet

When a reflog is deleted, e.g. when "git stash" clears its stashes, "git rev-parse --verify --quiet" dies: fatal: Log for refs/stash is empty. The reason is that the get_sha1() code path does not allow us to suppress this message. Pass the flags bitfield through get_sha1_with_context() so that read_ref_at() can suppress the message. Use get_sha1_with_context1() instead of get_sha1() in rev-parse so that the --quiet flag is honored. Signed-off-by: David Aguilar <davvid@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Aguilar committed Sep 18, 2014 at 20:45 UTC c41a87dd80cd32cfd6e2d670153a9b69dc627f71
6 files changed +58 -16
builtin/rev-parse.c
+4 -1
@@ -508,7 +508,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
508 int has_dashdash = 0;
509 int output_prefix = 0;
510 unsigned char sha1[20];
511 + unsigned int flags = 0;
512 const char *name = NULL;
513 + struct object_context unused;
514
515 if (argc > 1 && !strcmp("--parseopt", argv[1]))
516 return cmd_parseopt(argc - 1, argv + 1, prefix);
@@ -596,6 +598,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
598 }
599 if (!strcmp(arg, "--quiet") || !strcmp(arg, "-q")) {
600 quiet = 1;
601 + flags |= GET_SHA1_QUIETLY;
602 continue;
603 }
604 if (!strcmp(arg, "--short") ||
@@ -818,7 +821,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
821 name++;
822 type = REVERSED;
823 }
821 - if (!get_sha1(name, sha1)) {
824 + if (!get_sha1_with_context(name, flags, sha1, &unused)) {
825 if (verify)
826 revs_count++;
827 else
builtin/show-branch.c
+3 -2
@@ -723,6 +723,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
723 char nth_desc[256];
724 char *ref;
725 int base = 0;
726 + unsigned int flags = 0;
727
728 if (ac == 0) {
729 static const char *fake_av[2];
@@ -749,7 +750,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
750 /* Ah, that is a date spec... */
751 unsigned long at;
752 at = approxidate(reflog_base);
752 - read_ref_at(ref, at, -1, sha1, NULL,
753 + read_ref_at(ref, flags, at, -1, sha1, NULL,
754 NULL, NULL, &base);
755 }
756 }
@@ -760,7 +761,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
761 unsigned long timestamp;
762 int tz;
763
763 - if (read_ref_at(ref, 0, base+i, sha1, &logmsg,
764 + if (read_ref_at(ref, flags, 0, base+i, sha1, &logmsg,
765 &timestamp, &tz, NULL)) {
766 reflog = i;
767 break;
refs.c
+7 -3
@@ -3108,7 +3108,7 @@ static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,
3108 return 1;
3109 }
3110
3111 -int read_ref_at(const char *refname, unsigned long at_time, int cnt,
3111 +int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time, int cnt,
3112 unsigned char *sha1, char **msg,
3113 unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
3114 {
@@ -3126,8 +3126,12 @@ int read_ref_at(const char *refname, unsigned long at_time, int cnt,
3126
3127 for_each_reflog_ent_reverse(refname, read_ref_at_ent, &cb);
3128
3129 - if (!cb.reccnt)
3130 - die("Log for %s is empty.", refname);
3129 + if (!cb.reccnt) {
3130 + if (flags & GET_SHA1_QUIETLY)
3131 + exit(128);
3132 + else
3133 + die("Log for %s is empty.", refname);
3134 + }
3135 if (cb.found_it)
3136 return 0;
3137
refs.h
+2 -1
@@ -206,7 +206,8 @@ extern int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1, cons
206 int log_ref_setup(const char *refname, char *logfile, int bufsize);
207
208 /** Reads log for the value of ref during at_time. **/
209 -extern int read_ref_at(const char *refname, unsigned long at_time, int cnt,
209 +extern int read_ref_at(const char *refname, unsigned int flags,
210 + unsigned long at_time, int cnt,
211 unsigned char *sha1, char **msg,
212 unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt);
213
sha1_name.c
+15 -9
@@ -432,7 +432,8 @@ static inline int upstream_mark(const char *string, int len)
432 static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags);
433 static int interpret_nth_prior_checkout(const char *name, int namelen, struct strbuf *buf);
434
435 -static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
435 +static int get_sha1_basic(const char *str, int len, unsigned char *sha1,
436 + unsigned int flags)
437 {
438 static const char *warn_msg = "refname '%.*s' is ambiguous.";
439 static const char *object_name_msg = N_(
@@ -511,7 +512,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
512 if (!refs_found)
513 return -1;
514
514 - if (warn_ambiguous_refs &&
515 + if (warn_ambiguous_refs && !(flags & GET_SHA1_QUIETLY) &&
516 (refs_found > 1 ||
517 !get_short_sha1(str, len, tmp_sha1, GET_SHA1_QUIETLY)))
518 warning(warn_msg, len, str);
@@ -545,7 +546,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
546 return -1;
547 }
548 }
548 - if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
549 + if (read_ref_at(real_ref, flags, at_time, nth, sha1, NULL,
550 &co_time, &co_tz, &co_cnt)) {
551 if (!len) {
552 if (starts_with(real_ref, "refs/heads/")) {
@@ -557,11 +558,16 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
558 len = 4;
559 }
560 }
560 - if (at_time)
561 - warning("Log for '%.*s' only goes "
562 - "back to %s.", len, str,
563 - show_date(co_time, co_tz, DATE_RFC2822));
564 - else {
561 + if (at_time) {
562 + if (!(flags & GET_SHA1_QUIETLY)) {
563 + warning("Log for '%.*s' only goes "
564 + "back to %s.", len, str,
565 + show_date(co_time, co_tz, DATE_RFC2822));
566 + }
567 + } else {
568 + if (flags & GET_SHA1_QUIETLY) {
569 + exit(128);
570 + }
571 die("Log for '%.*s' only has %d entries.",
572 len, str, co_cnt);
573 }
@@ -801,7 +807,7 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned l
807 if (!ret)
808 return 0;
809
804 - ret = get_sha1_basic(name, len, sha1);
810 + ret = get_sha1_basic(name, len, sha1, lookup_flags);
811 if (!ret)
812 return 0;
813
t/t1503-rev-parse-verify.sh
+27
@@ -83,6 +83,33 @@ test_expect_success 'fails silently when using -q' '
83 test_must_be_empty error
84 '
85
86 +test_expect_success 'fails silently when using -q with deleted reflogs' '
87 + ref=$(git rev-parse HEAD) &&
88 + : >.git/logs/refs/test &&
89 + git update-ref -m "message for refs/test" refs/test "$ref" &&
90 + git reflog delete --updateref --rewrite refs/test@{0} &&
91 + test_must_fail git rev-parse -q --verify refs/test@{0} >error 2>&1 &&
92 + test_must_be_empty error
93 +'
94 +
95 +test_expect_success 'fails silently when using -q with not enough reflogs' '
96 + ref=$(git rev-parse HEAD) &&
97 + : >.git/logs/refs/test2 &&
98 + git update-ref -m "message for refs/test2" refs/test2 "$ref" &&
99 + test_must_fail git rev-parse -q --verify refs/test2@{999} >error 2>&1 &&
100 + test_must_be_empty error
101 +'
102 +
103 +test_expect_success 'succeeds silently with -q and reflogs that do not go far back enough in time' '
104 + ref=$(git rev-parse HEAD) &&
105 + : >.git/logs/refs/test3 &&
106 + git update-ref -m "message for refs/test3" refs/test3 "$ref" &&
107 + git rev-parse -q --verify refs/test3@{1.year.ago} >actual 2>error &&
108 + test_must_be_empty error &&
109 + echo "$ref" >expect &&
110 + test_cmp expect actual
111 +'
112 +
113 test_expect_success 'no stdout output on error' '
114 test -z "$(git rev-parse --verify)" &&
115 test -z "$(git rev-parse --verify foo)" &&