+#define _XOPEN_SOURCE /* glibc2 needs this */
+#include <time.h>
+#include <ctype.h>
#include "cache.h"
/*
#define SEEN 0x10000
static int show_edges = 0;
+static int basemask = 0;
struct parent {
struct revision *parent;
struct revision {
unsigned int flags;
unsigned char sha1[20];
+ unsigned long date;
struct parent *parent;
};
return 1;
}
+static unsigned long parse_time(const char *buf)
+{
+ char c, *p;
+ char buffer[100];
+ struct tm tm;
+ const char *formats[] = {
+ "%c",
+ "%a %b %d %T %y",
+ NULL
+ };
+ const char **fmt = formats;
+
+ p = buffer;
+ while (isspace(c = *buf))
+ buf++;
+ while ((c = *buf++) != '\n')
+ *p++ = c;
+ *p++ = 0;
+ buf = buffer;
+ memset(&tm, 0, sizeof(tm));
+ do {
+ const char *next = strptime(buf, *fmt, &tm);
+ fmt++;
+ if (next) {
+ if (!*next)
+ return mktime(&tm);
+ buf = next;
+ }
+ } while (*buf && *fmt);
+ return mktime(&tm);
+}
+
+
+static unsigned long parse_commit_date(const char *buf)
+{
+ if (memcmp(buf, "author", 6))
+ return 0;
+ while (*buf++ != '\n')
+ /* nada */;
+ if (memcmp(buf, "committer", 9))
+ return 0;
+ while (*buf++ != '>')
+ /* nada */;
+ return parse_time(buf);
+}
+
static int parse_commit(unsigned char *sha1)
{
struct revision *rev = lookup_rev(sha1);
if (!(rev->flags & SEEN)) {
- void *buffer;
+ void *buffer, *bufptr;
unsigned long size;
char type[20];
unsigned char parent[20];
rev->flags |= SEEN;
- buffer = read_sha1_file(sha1, type, &size);
+ buffer = bufptr = read_sha1_file(sha1, type, &size);
if (!buffer || strcmp(type, "commit"))
return -1;
- buffer += 46; /* "tree " + "hex sha1" + "\n" */
- while (!memcmp(buffer, "parent ", 7) && !get_sha1_hex(buffer+7, parent)) {
+ bufptr += 46; /* "tree " + "hex sha1" + "\n" */
+ while (!memcmp(bufptr, "parent ", 7) && !get_sha1_hex(bufptr+7, parent)) {
add_relationship(rev, parent);
parse_commit(parent);
- buffer += 48; /* "parent " + "hex sha1" + "\n" */
+ bufptr += 48; /* "parent " + "hex sha1" + "\n" */
}
+ rev->date = parse_commit_date(bufptr);
+ free(buffer);
}
return 0;
}
static void read_cache_file(const char *path)
{
FILE *file = fopen(path, "r");
- char line[100];
+ char line[500];
if (!file)
usage("bad revtree cache file (%s)", path);
while (fgets(line, sizeof(line), file)) {
- unsigned char sha1[20], parent[20];
+ unsigned long date;
+ unsigned char sha1[20];
struct revision *rev;
-
- if (get_sha1_hex(line, sha1) || get_sha1_hex(line + 41, parent))
- usage("bad rev-tree cache file %s", path);
+ const char *buf;
+
+ if (sscanf(line, "%lu", &date) != 1)
+ break;
+ buf = strchr(line, ' ');
+ if (!buf)
+ break;
+ if (get_sha1_hex(buf+1, sha1))
+ break;
rev = lookup_rev(sha1);
rev->flags |= SEEN;
- add_relationship(rev, parent);
+ rev->date = date;
+
+ /* parents? */
+ while ((buf = strchr(buf+1, ' ')) != NULL) {
+ unsigned char parent[20];
+ if (get_sha1_hex(buf + 1, parent))
+ break;
+ add_relationship(rev, parent);
+ }
}
fclose(file);
}
}
return 0;
}
+ if (mask & basemask)
+ return 0;
+
return 1;
}
continue;
}
+ if (arg[0] == '^') {
+ arg++;
+ basemask |= 1<<nr;
+ }
if (nr >= MAX_COMMITS || get_sha1_hex(arg, sha1[nr]))
usage("rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id>]");
parse_commit(sha1[nr]);
if (!interesting(rev))
continue;
- printf("%x %s", marked(rev), sha1_to_hex(rev->sha1));
+ printf("%lu %s:%d", rev->date, sha1_to_hex(rev->sha1), marked(rev));
p = rev->parent;
while (p) {
- printf(" %s", sha1_to_hex(p->parent->sha1));
+ printf(" %s:%d", sha1_to_hex(p->parent->sha1), marked(p->parent));
p = p->next;
}
printf("\n");