summaryrefslogtreecommitdiff
path: root/sha1_name.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 /sha1_name.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 'sha1_name.c')
-rw-r--r--sha1_name.c59
1 files changed, 42 insertions, 17 deletions
diff --git a/sha1_name.c b/sha1_name.c
index dc6835520c..3ac3ab4f58 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -4,6 +4,7 @@
#include "tree.h"
#include "blob.h"
#include "tree-walk.h"
+#include "refs.h"
static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
{
@@ -245,36 +246,60 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
"refs/remotes/%.*s/HEAD",
NULL
};
- const char **p;
- const char *warning = "warning: refname '%.*s' is ambiguous.\n";
- char *pathname;
- int already_found = 0;
+ static const char *warning = "warning: refname '%.*s' is ambiguous.\n";
+ const char **p, *pathname;
+ char *real_path = NULL;
+ int refs_found = 0, at_mark;
+ unsigned long at_time = (unsigned long)-1;
unsigned char *this_result;
unsigned char sha1_from_ref[20];
if (len == 40 && !get_sha1_hex(str, sha1))
return 0;
+ /* At a given period of time? "@2 hours ago" */
+ for (at_mark = 1; at_mark < len; at_mark++) {
+ if (str[at_mark] == '@') {
+ int date_len = len - at_mark - 1;
+ char *date_spec = xmalloc(date_len + 1);
+ strncpy(date_spec, str + at_mark + 1, date_len);
+ date_spec[date_len] = 0;
+ at_time = approxidate(date_spec);
+ free(date_spec);
+ len = at_mark;
+ }
+ }
+
/* Accept only unambiguous ref paths. */
if (ambiguous_path(str, len))
return -1;
for (p = fmt; *p; p++) {
- this_result = already_found ? sha1_from_ref : sha1;
- pathname = git_path(*p, len, str);
- if (!read_ref(pathname, this_result)) {
- if (warn_ambiguous_refs) {
- if (already_found)
- fprintf(stderr, warning, len, str);
- already_found++;
- }
- else
- return 0;
+ this_result = refs_found ? sha1_from_ref : sha1;
+ pathname = resolve_ref(git_path(*p, len, str), this_result, 1);
+ if (pathname) {
+ if (!refs_found++)
+ real_path = strdup(pathname);
+ if (!warn_ambiguous_refs)
+ break;
}
}
- if (already_found)
- return 0;
- return -1;
+
+ if (!refs_found)
+ return -1;
+
+ if (warn_ambiguous_refs && refs_found > 1)
+ fprintf(stderr, warning, len, str);
+
+ if (at_time != (unsigned long)-1) {
+ read_ref_at(
+ real_path + strlen(git_path(".")) - 1,
+ at_time,
+ sha1);
+ }
+
+ free(real_path);
+ return 0;
}
static int get_sha1_1(const char *name, int len, unsigned char *sha1);