summaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
authorShawn Pearce <spearce@spearce.org>2006-05-17 05:56:09 -0400
committerJunio C Hamano <junkio@cox.net>2006-05-17 17:36:36 -0700
commitd556fae2c0ea063f15ea4c3678fe931cc426f1ca (patch)
treee6913e22bdc72e0222328ea8ae2b6ac5201c8bcd /refs.c
parent6de08ae688b9f2426410add155079e04baff33bd (diff)
downloadgit-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.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/refs.c b/refs.c
index 4be75a59aa..4c99e3729f 100644
--- a/refs.c
+++ b/refs.c
@@ -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;
+}