diff options
author | Shawn Pearce <spearce@spearce.org> | 2006-05-17 05:56:09 -0400 |
---|---|---|
committer | Junio C Hamano <junkio@cox.net> | 2006-05-17 17:36:36 -0700 |
commit | d556fae2c0ea063f15ea4c3678fe931cc426f1ca (patch) | |
tree | e6913e22bdc72e0222328ea8ae2b6ac5201c8bcd /refs.c | |
parent | 6de08ae688b9f2426410add155079e04baff33bd (diff) | |
download | git-d556fae2c0ea063f15ea4c3678fe931cc426f1ca.tar.gz |
Support 'master@2 hours ago' syntax
Extended sha1 expressions may now include date specifications
which indicate a point in time within the local repository's
history. If the ref indicated to the left of '@' has a log in
$GIT_DIR/logs/<ref> then the value of the ref at the time indicated
by the specification is obtained from the ref's log.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'refs.c')
-rw-r--r-- | refs.c | 53 |
1 files changed, 53 insertions, 0 deletions
@@ -429,3 +429,56 @@ int write_ref_sha1(struct ref_lock *lock, unlock_ref(lock); return 0; } + +int read_ref_at(const char *ref, unsigned long at_time, unsigned char *sha1) +{ + const char *logfile, *logdata, *logend, *rec, *c; + char *tz_c; + int logfd, tz; + struct stat st; + unsigned long date; + + logfile = git_path("logs/%s", ref); + logfd = open(logfile, O_RDONLY, 0); + if (logfd < 0) + die("Unable to read log %s: %s", logfile, strerror(errno)); + fstat(logfd, &st); + if (!st.st_size) + die("Log %s is empty.", logfile); + logdata = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd, 0); + close(logfd); + + rec = logend = logdata + st.st_size; + while (logdata < rec) { + if (logdata < rec && *(rec-1) == '\n') + rec--; + while (logdata < rec && *(rec-1) != '\n') + rec--; + c = rec; + while (c < logend && *c != '>' && *c != '\n') + c++; + if (c == logend || *c == '\n') + die("Log %s is corrupt.", logfile); + date = strtoul(c, NULL, 10); + if (date <= at_time) { + if (get_sha1_hex(rec + 41, sha1)) + die("Log %s is corrupt.", logfile); + munmap((void*)logdata, st.st_size); + return 0; + } + } + + c = logdata; + while (c < logend && *c != '>' && *c != '\n') + c++; + if (c == logend || *c == '\n') + die("Log %s is corrupt.", logfile); + date = strtoul(c, &tz_c, 10); + tz = strtoul(tz_c, NULL, 10); + if (get_sha1_hex(logdata, sha1)) + die("Log %s is corrupt.", logfile); + munmap((void*)logdata, st.st_size); + fprintf(stderr, "warning: Log %s only goes back to %s.\n", + logfile, show_rfc2822_date(date, tz)); + return 0; +} |