Merge branch 'da/rev-parse-verify-quiet'
authorJunio C Hamano <gitster@pobox.com>
Mon, 29 Sep 2014 19:36:10 +0000 (12:36 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 29 Sep 2014 19:36:10 +0000 (12:36 -0700)
"rev-parse --verify --quiet $name" is meant to quietly exit with a
non-zero status when $name is not a valid object name, but still
gave error messages in some cases.

* da/rev-parse-verify-quiet:
stash: prefer --quiet over shell redirection of the standard error stream
refs: make rev-parse --quiet actually quiet
t1503: use test_must_be_empty
Documentation: a note about stdout for git rev-parse --verify --quiet

Documentation/git-rev-parse.txt
builtin/rev-parse.c
builtin/show-branch.c
git-stash.sh
refs.c
refs.h
sha1_name.c
t/t1503-rev-parse-verify.sh
index 0b84769bd91b5894a246ff3d499dca1ffba339ac..fa4a8c3afcb93a5fc72e9d0a5dc798d773e0bb9e 100644 (file)
@@ -114,6 +114,7 @@ can be used.
        Only meaningful in `--verify` mode. Do not output an error
        message if the first argument is not a valid object name;
        instead exit with non-zero status silently.
+       SHA-1s for valid object names are printed to stdout on success.
 
 --sq::
        Usually the output is made one line per flag and
index c911b456dedd648e36a876c6175c23e1ef028a43..35d3c43ed656bf28b78501426f4502c0dff1e7b0 100644 (file)
@@ -508,7 +508,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
        int has_dashdash = 0;
        int output_prefix = 0;
        unsigned char sha1[20];
+       unsigned int flags = 0;
        const char *name = NULL;
+       struct object_context unused;
 
        if (argc > 1 && !strcmp("--parseopt", argv[1]))
                return cmd_parseopt(argc - 1, argv + 1, prefix);
@@ -596,6 +598,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                        }
                        if (!strcmp(arg, "--quiet") || !strcmp(arg, "-q")) {
                                quiet = 1;
+                               flags |= GET_SHA1_QUIETLY;
                                continue;
                        }
                        if (!strcmp(arg, "--short") ||
@@ -818,7 +821,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
                        name++;
                        type = REVERSED;
                }
-               if (!get_sha1(name, sha1)) {
+               if (!get_sha1_with_context(name, flags, sha1, &unused)) {
                        if (verify)
                                revs_count++;
                        else
index a1275237ee19473e18397e94868d24d52231d1c3..199b081e9b805cceb1f2097f2d33966e5f8ff167 100644 (file)
@@ -723,6 +723,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                char nth_desc[256];
                char *ref;
                int base = 0;
+               unsigned int flags = 0;
 
                if (ac == 0) {
                        static const char *fake_av[2];
@@ -749,7 +750,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                                /* Ah, that is a date spec... */
                                unsigned long at;
                                at = approxidate(reflog_base);
-                               read_ref_at(ref, at, -1, sha1, NULL,
+                               read_ref_at(ref, flags, at, -1, sha1, NULL,
                                            NULL, NULL, &base);
                        }
                }
@@ -760,7 +761,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
                        unsigned long timestamp;
                        int tz;
 
-                       if (read_ref_at(ref, 0, base+i, sha1, &logmsg,
+                       if (read_ref_at(ref, flags, 0, base+i, sha1, &logmsg,
                                        &timestamp, &tz, NULL)) {
                                reflog = i;
                                break;
index 0158c7338685c8ccbc31766927f905b455a444c2..d4cf818be9488f1b94fdf4766a8f73db6bfd1029 100755 (executable)
@@ -50,7 +50,7 @@ clear_stash () {
        then
                die "$(gettext "git stash clear with parameters is unimplemented")"
        fi
-       if current=$(git rev-parse --verify $ref_stash 2>/dev/null)
+       if current=$(git rev-parse --verify --quiet $ref_stash)
        then
                git update-ref -d $ref_stash $current
        fi
@@ -292,7 +292,7 @@ save_stash () {
 }
 
 have_stash () {
-       git rev-parse --verify $ref_stash >/dev/null 2>&1
+       git rev-parse --verify --quiet $ref_stash >/dev/null
 }
 
 list_stash () {
@@ -392,12 +392,12 @@ parse_flags_and_rev()
                ;;
        esac
 
-       REV=$(git rev-parse --quiet --symbolic --verify "$1" 2>/dev/null) || {
+       REV=$(git rev-parse --symbolic --verify --quiet "$1") || {
                reference="$1"
                die "$(eval_gettext "\$reference is not a valid reference")"
        }
 
-       i_commit=$(git rev-parse --quiet --verify "$REV^2" 2>/dev/null) &&
+       i_commit=$(git rev-parse --verify --quiet "$REV^2") &&
        set -- $(git rev-parse "$REV" "$REV^1" "$REV:" "$REV^1:" "$REV^2:" 2>/dev/null) &&
        s=$1 &&
        w_commit=$1 &&
@@ -409,7 +409,7 @@ parse_flags_and_rev()
        test "$ref_stash" = "$(git rev-parse --symbolic-full-name "${REV%@*}")" &&
        IS_STASH_REF=t
 
-       u_commit=$(git rev-parse --quiet --verify "$REV^3" 2>/dev/null) &&
+       u_commit=$(git rev-parse --verify --quiet "$REV^3") &&
        u_tree=$(git rev-parse "$REV^3:" 2>/dev/null)
 }
 
@@ -531,7 +531,8 @@ drop_stash () {
                die "$(eval_gettext "\${REV}: Could not drop stash entry")"
 
        # clear_stash if we just dropped the last stash entry
-       git rev-parse --verify "$ref_stash@{0}" >/dev/null 2>&1 || clear_stash
+       git rev-parse --verify --quiet "$ref_stash@{0}" >/dev/null ||
+       clear_stash
 }
 
 apply_to_branch () {
diff --git a/refs.c b/refs.c
index 311a6b52b1a9b65c997357e2d1d80e0e4743b2ca..ffd45e92922ec52dccccfaecf1ceaf29f9231337 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -3159,7 +3159,7 @@ static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,
        return 1;
 }
 
-int read_ref_at(const char *refname, unsigned long at_time, int cnt,
+int read_ref_at(const char *refname, unsigned int flags, unsigned long at_time, int cnt,
                unsigned char *sha1, char **msg,
                unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt)
 {
@@ -3177,8 +3177,12 @@ int read_ref_at(const char *refname, unsigned long at_time, int cnt,
 
        for_each_reflog_ent_reverse(refname, read_ref_at_ent, &cb);
 
-       if (!cb.reccnt)
-               die("Log for %s is empty.", refname);
+       if (!cb.reccnt) {
+               if (flags & GET_SHA1_QUIETLY)
+                       exit(128);
+               else
+                       die("Log for %s is empty.", refname);
+       }
        if (cb.found_it)
                return 0;
 
diff --git a/refs.h b/refs.h
index 10fc3a2634409571d38a1322b9853547d216945b..2328f06e77d34d76a1f4affedcca2c51ff9e0093 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -206,7 +206,8 @@ extern int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1, cons
 int log_ref_setup(const char *refname, char *logfile, int bufsize);
 
 /** Reads log for the value of ref during at_time. **/
-extern int read_ref_at(const char *refname, unsigned long at_time, int cnt,
+extern int read_ref_at(const char *refname, unsigned int flags,
+                      unsigned long at_time, int cnt,
                       unsigned char *sha1, char **msg,
                       unsigned long *cutoff_time, int *cutoff_tz, int *cutoff_cnt);
 
index 7098b10e3db0caef02ae2daef8f0624e641aada4..5b004f513b999b31b7968b22dde955c859704853 100644 (file)
@@ -432,7 +432,8 @@ static inline int upstream_mark(const char *string, int len)
 static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags);
 static int interpret_nth_prior_checkout(const char *name, int namelen, struct strbuf *buf);
 
-static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
+static int get_sha1_basic(const char *str, int len, unsigned char *sha1,
+                         unsigned int flags)
 {
        static const char *warn_msg = "refname '%.*s' is ambiguous.";
        static const char *object_name_msg = N_(
@@ -511,7 +512,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
        if (!refs_found)
                return -1;
 
-       if (warn_ambiguous_refs &&
+       if (warn_ambiguous_refs && !(flags & GET_SHA1_QUIETLY) &&
            (refs_found > 1 ||
             !get_short_sha1(str, len, tmp_sha1, GET_SHA1_QUIETLY)))
                warning(warn_msg, len, str);
@@ -545,7 +546,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
                                return -1;
                        }
                }
-               if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
+               if (read_ref_at(real_ref, flags, at_time, nth, sha1, NULL,
                                &co_time, &co_tz, &co_cnt)) {
                        if (!len) {
                                if (starts_with(real_ref, "refs/heads/")) {
@@ -557,11 +558,16 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
                                        len = 4;
                                }
                        }
-                       if (at_time)
-                               warning("Log for '%.*s' only goes "
-                                       "back to %s.", len, str,
-                                       show_date(co_time, co_tz, DATE_RFC2822));
-                       else {
+                       if (at_time) {
+                               if (!(flags & GET_SHA1_QUIETLY)) {
+                                       warning("Log for '%.*s' only goes "
+                                               "back to %s.", len, str,
+                                               show_date(co_time, co_tz, DATE_RFC2822));
+                               }
+                       } else {
+                               if (flags & GET_SHA1_QUIETLY) {
+                                       exit(128);
+                               }
                                die("Log for '%.*s' only has %d entries.",
                                    len, str, co_cnt);
                        }
@@ -801,7 +807,7 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned l
        if (!ret)
                return 0;
 
-       ret = get_sha1_basic(name, len, sha1);
+       ret = get_sha1_basic(name, len, sha1, lookup_flags);
        if (!ret)
                return 0;
 
index 813cc1b3e29ec840deb63ad9c3c1dffd2187cdc5..823fe1d79924b68950a59ffde902b16db29205b6 100755 (executable)
@@ -72,15 +72,42 @@ test_expect_success 'fails with any bad rev or many good revs' '
 
 test_expect_success 'fails silently when using -q' '
        test_must_fail git rev-parse --verify --quiet 2>error &&
-       test -z "$(cat error)" &&
+       test_must_be_empty error &&
        test_must_fail git rev-parse -q --verify foo 2>error &&
-       test -z "$(cat error)" &&
+       test_must_be_empty error &&
        test_must_fail git rev-parse --verify -q HEAD bar 2>error &&
-       test -z "$(cat error)" &&
+       test_must_be_empty error &&
        test_must_fail git rev-parse --quiet --verify baz HEAD 2>error &&
-       test -z "$(cat error)" &&
+       test_must_be_empty error &&
        test_must_fail git rev-parse -q --verify $HASH2 HEAD 2>error &&
-       test -z "$(cat error)"
+       test_must_be_empty error
+'
+
+test_expect_success 'fails silently when using -q with deleted reflogs' '
+       ref=$(git rev-parse HEAD) &&
+       : >.git/logs/refs/test &&
+       git update-ref -m "message for refs/test" refs/test "$ref" &&
+       git reflog delete --updateref --rewrite refs/test@{0} &&
+       test_must_fail git rev-parse -q --verify refs/test@{0} >error 2>&1 &&
+       test_must_be_empty error
+'
+
+test_expect_success 'fails silently when using -q with not enough reflogs' '
+       ref=$(git rev-parse HEAD) &&
+       : >.git/logs/refs/test2 &&
+       git update-ref -m "message for refs/test2" refs/test2 "$ref" &&
+       test_must_fail git rev-parse -q --verify refs/test2@{999} >error 2>&1 &&
+       test_must_be_empty error
+'
+
+test_expect_success 'succeeds silently with -q and reflogs that do not go far back enough in time' '
+       ref=$(git rev-parse HEAD) &&
+       : >.git/logs/refs/test3 &&
+       git update-ref -m "message for refs/test3" refs/test3 "$ref" &&
+       git rev-parse -q --verify refs/test3@{1.year.ago} >actual 2>error &&
+       test_must_be_empty error &&
+       echo "$ref" >expect &&
+       test_cmp expect actual
 '
 
 test_expect_success 'no stdout output on error' '