Make "rev-tree" able to read its own output again from the cache.

Also, add "date" information to the output so that you can do something
like this:

	rev-tree `cat .git/HEAD` | sort -nr | cut -d' ' -f2 | while read i; do cat-file commit $i; done

which basically becomes a "git log" (aka "git changes") where things are
sorted by time.
maint
Linus Torvalds 2005-04-12 13:40:03 -07:00
parent 727ff27787
commit 40e88b95cd
1 changed files with 73 additions and 6 deletions

View File

@ -1,3 +1,6 @@
#define _XOPEN_SOURCE /* glibc2 needs this */
#include <time.h>
#include <ctype.h>
#include "cache.h" #include "cache.h"


/* /*
@ -24,6 +27,7 @@ struct parent {
struct revision { struct revision {
unsigned int flags; unsigned int flags;
unsigned char sha1[20]; unsigned char sha1[20];
unsigned long date;
struct parent *parent; struct parent *parent;
}; };


@ -97,6 +101,52 @@ static int add_relationship(struct revision *rev, unsigned char *parent_sha)
return 1; 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) static int parse_commit(unsigned char *sha1)
{ {
struct revision *rev = lookup_rev(sha1); struct revision *rev = lookup_rev(sha1);
@ -117,6 +167,8 @@ static int parse_commit(unsigned char *sha1)
parse_commit(parent); parse_commit(parent);
buffer += 48; /* "parent " + "hex sha1" + "\n" */ buffer += 48; /* "parent " + "hex sha1" + "\n" */
} }
rev->date = parse_commit_date(buffer);
free(buffer);
} }
return 0; return 0;
} }
@ -124,21 +176,36 @@ static int parse_commit(unsigned char *sha1)
static void read_cache_file(const char *path) static void read_cache_file(const char *path)
{ {
FILE *file = fopen(path, "r"); FILE *file = fopen(path, "r");
char line[100]; char line[500];


if (!file) if (!file)
usage("bad revtree cache file (%s)", path); usage("bad revtree cache file (%s)", path);


while (fgets(line, sizeof(line), file)) { while (fgets(line, sizeof(line), file)) {
unsigned char sha1[20], parent[20]; unsigned long date;
unsigned char sha1[20];
struct revision *rev; struct revision *rev;
const char *buf;


if (get_sha1_hex(line, sha1) || get_sha1_hex(line + 41, parent)) if (sscanf(line, "%lu", &date) != 1)
usage("bad rev-tree cache file %s", path); break;
buf = strchr(line, ' ');
if (!buf)
break;
if (get_sha1_hex(buf+1, sha1))
break;
rev = lookup_rev(sha1); rev = lookup_rev(sha1);
rev->flags |= SEEN; rev->flags |= SEEN;
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); add_relationship(rev, parent);
} }
}
fclose(file); fclose(file);
} }


@ -244,7 +311,7 @@ int main(int argc, char **argv)
if (!interesting(rev)) if (!interesting(rev))
continue; continue;


printf("%s:%d", sha1_to_hex(rev->sha1), marked(rev)); printf("%lu %s:%d", rev->date, sha1_to_hex(rev->sha1), marked(rev));
p = rev->parent; p = rev->parent;
while (p) { while (p) {
printf(" %s:%d", sha1_to_hex(p->parent->sha1), marked(p->parent)); printf(" %s:%d", sha1_to_hex(p->parent->sha1), marked(p->parent));