avoid null SHA1 in oldest reflog
authorJeff King <peff@peff.net>
Tue, 8 Jul 2008 04:38:54 +0000 (00:38 -0400)
committerJunio C Hamano <gitster@pobox.com>
Tue, 8 Jul 2008 20:57:27 +0000 (13:57 -0700)
When the user specifies a ref by a reflog entry older than
one we have (e.g., "HEAD@{20 years ago"}), we issue a
warning and give them the "from" value of the oldest reflog
entry. That is, we say "we don't know what happened before
this entry, but before this we know we had some particular
SHA1".

However, the oldest reflog entry is often a creation event
such as clone or branch creation. In this case, the entry
claims that the ref went from "00000..." (the null sha1) to
the new value, and the reflog lookup returns the null sha1.

While this is technically correct (the entry tells us that
the ref didn't exist at the specified time) it is not
terribly useful to the end user. What they probably want
instead is "the oldest useful sha1 that this ref ever had".
This patch changes the behavior such that if the oldest ref
would return the null sha1, it instead returns the first
value the ref ever had.

We never discovered this problem in the test scripts because
we created "fake" reflogs that had only a specified segment
of history. This patch updates the tests with a creation
event at the beginning of history.

Signed-off-by: Jeff King <peff@peff.net>
Acked-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs.c
t/t1400-update-ref.sh

diff --git a/refs.c b/refs.c
index 9e8e8581ba981ca88366b614f1e8749cfe8a6ae5..6c6e9e5e1963e74307266b432e58a5fe51a9ce39 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1412,6 +1412,10 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
        tz = strtoul(tz_c, NULL, 10);
        if (get_sha1_hex(logdata, sha1))
                die("Log %s is corrupt.", logfile);
+       if (is_null_sha1(sha1)) {
+               if (get_sha1_hex(logdata + 41, sha1))
+                       die("Log %s is corrupt.", logfile);
+       }
        if (msg)
                *msg = ref_msg(logdata, logend);
        munmap(log_mapped, mapsz);
index f387d46f1a17ac9f9d3319c4da7e30a6c6326c67..ca99d37616aaaae9584ecfd1c5d74378c727d077 100755 (executable)
@@ -155,7 +155,8 @@ rm -f .git/$m .git/logs/$m expect
 
 git update-ref $m $D
 cat >.git/logs/$m <<EOF
-$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
+0000000000000000000000000000000000000000 $C $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150320 -0500
+$C $A $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150350 -0500
 $A $B $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150380 -0500
 $F $Z $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150680 -0500
 $Z $E $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150980 -0500
@@ -186,6 +187,12 @@ test_expect_success \
        'Query "master@{May 26 2005 23:32:00}" (exactly history start)' \
        'rm -f o e
         git rev-parse --verify "master@{May 26 2005 23:32:00}" >o 2>e &&
+        test '"$C"' = $(cat o) &&
+        test "" = "$(cat e)"'
+test_expect_success \
+       'Query "master@{May 26 2005 23:32:30}" (first non-creation change)' \
+       'rm -f o e
+        git rev-parse --verify "master@{May 26 2005 23:32:30}" >o 2>e &&
         test '"$A"' = $(cat o) &&
         test "" = "$(cat e)"'
 test_expect_success \