Browse Source
This implements the parsing functions. Signed-Off-By: Daniel Barkalow <barkalow@iabervon.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>maint


4 changed files with 272 additions and 0 deletions
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
#include "blob.h" |
||||
#include "cache.h" |
||||
#include <stdlib.h> |
||||
|
||||
const char *blob_type = "blob"; |
||||
|
||||
struct blob *lookup_blob(unsigned char *sha1) |
||||
{ |
||||
struct object *obj = lookup_object(sha1); |
||||
if (!obj) { |
||||
struct blob *ret = malloc(sizeof(struct blob)); |
||||
memset(ret, 0, sizeof(struct blob)); |
||||
created_object(sha1, &ret->object); |
||||
ret->object.type = blob_type; |
||||
ret->object.parsed = 1; |
||||
return ret; |
||||
} |
||||
if (obj->parsed && obj->type != blob_type) { |
||||
error("Object %s is a %s, not a blob", |
||||
sha1_to_hex(sha1), obj->type); |
||||
return NULL; |
||||
} |
||||
return (struct blob *) obj; |
||||
} |
@ -0,0 +1,85 @@
@@ -0,0 +1,85 @@
|
||||
#include "commit.h" |
||||
#include "cache.h" |
||||
#include <string.h> |
||||
|
||||
const char *commit_type = "commit"; |
||||
|
||||
struct commit *lookup_commit(unsigned char *sha1) |
||||
{ |
||||
struct object *obj = lookup_object(sha1); |
||||
if (!obj) { |
||||
struct commit *ret = malloc(sizeof(struct commit)); |
||||
memset(ret, 0, sizeof(struct commit)); |
||||
created_object(sha1, &ret->object); |
||||
return ret; |
||||
} |
||||
if (obj->parsed && obj->type != commit_type) { |
||||
error("Object %s is a %s, not a commit", |
||||
sha1_to_hex(sha1), obj->type); |
||||
return NULL; |
||||
} |
||||
return (struct commit *) obj; |
||||
} |
||||
|
||||
static unsigned long parse_commit_date(const char *buf) |
||||
{ |
||||
unsigned long date; |
||||
|
||||
if (memcmp(buf, "author", 6)) |
||||
return 0; |
||||
while (*buf++ != '\n') |
||||
/* nada */; |
||||
if (memcmp(buf, "committer", 9)) |
||||
return 0; |
||||
while (*buf++ != '>') |
||||
/* nada */; |
||||
date = strtoul(buf, NULL, 10); |
||||
if (date == ULONG_MAX) |
||||
date = 0; |
||||
return date; |
||||
} |
||||
|
||||
int parse_commit(struct commit *item) |
||||
{ |
||||
char type[20]; |
||||
void * buffer, *bufptr; |
||||
unsigned long size; |
||||
unsigned char parent[20]; |
||||
if (item->object.parsed) |
||||
return 0; |
||||
item->object.parsed = 1; |
||||
buffer = bufptr = read_sha1_file(item->object.sha1, type, &size); |
||||
if (!buffer) |
||||
return error("Could not read %s", |
||||
sha1_to_hex(item->object.sha1)); |
||||
if (strcmp(type, commit_type)) |
||||
return error("Object %s not a commit", |
||||
sha1_to_hex(item->object.sha1)); |
||||
item->object.type = commit_type; |
||||
get_sha1_hex(bufptr + 5, parent); |
||||
item->tree = lookup_tree(parent); |
||||
add_ref(&item->object, &item->tree->object); |
||||
bufptr += 46; /* "tree " + "hex sha1" + "\n" */ |
||||
while (!memcmp(bufptr, "parent ", 7) && |
||||
!get_sha1_hex(bufptr + 7, parent)) { |
||||
struct commit_list *new_parent = |
||||
malloc(sizeof(struct commit_list)); |
||||
new_parent->next = item->parents; |
||||
new_parent->item = lookup_commit(parent); |
||||
add_ref(&item->object, &new_parent->item->object); |
||||
item->parents = new_parent; |
||||
bufptr += 48; |
||||
} |
||||
item->date = parse_commit_date(bufptr); |
||||
free(buffer); |
||||
return 0; |
||||
} |
||||
|
||||
void free_commit_list(struct commit_list *list) |
||||
{ |
||||
while (list) { |
||||
struct commit_list *temp = list; |
||||
list = temp->next; |
||||
free(temp); |
||||
} |
||||
} |
@ -0,0 +1,96 @@
@@ -0,0 +1,96 @@
|
||||
#include "object.h" |
||||
#include "cache.h" |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
struct object **objs; |
||||
int nr_objs; |
||||
static int obj_allocs; |
||||
|
||||
static int find_object(unsigned char *sha1) |
||||
{ |
||||
int first = 0, last = nr_objs; |
||||
|
||||
while (first < last) { |
||||
int next = (first + last) / 2; |
||||
struct object *obj = objs[next]; |
||||
int cmp; |
||||
|
||||
cmp = memcmp(sha1, obj->sha1, 20); |
||||
if (!cmp) |
||||
return next; |
||||
if (cmp < 0) { |
||||
last = next; |
||||
continue; |
||||
} |
||||
first = next+1; |
||||
} |
||||
return -first-1; |
||||
} |
||||
|
||||
struct object *lookup_object(unsigned char *sha1) |
||||
{ |
||||
int pos = find_object(sha1); |
||||
if (pos >= 0) |
||||
return objs[pos]; |
||||
return NULL; |
||||
} |
||||
|
||||
void created_object(unsigned char *sha1, struct object *obj) |
||||
{ |
||||
int pos = find_object(sha1); |
||||
|
||||
obj->parsed = 0; |
||||
memcpy(obj->sha1, sha1, 20); |
||||
obj->type = NULL; |
||||
obj->refs = NULL; |
||||
obj->used = 0; |
||||
|
||||
if (pos >= 0) |
||||
die("Inserting %s twice\n", sha1_to_hex(sha1)); |
||||
pos = -pos-1; |
||||
|
||||
if (obj_allocs == nr_objs) { |
||||
obj_allocs = alloc_nr(obj_allocs); |
||||
objs = realloc(objs, obj_allocs * sizeof(struct object *)); |
||||
} |
||||
|
||||
/* Insert it into the right place */ |
||||
memmove(objs + pos + 1, objs + pos, (nr_objs - pos) * |
||||
sizeof(struct object *)); |
||||
|
||||
objs[pos] = obj; |
||||
nr_objs++; |
||||
} |
||||
|
||||
void add_ref(struct object *refer, struct object *target) |
||||
{ |
||||
struct object_list **pp = &refer->refs; |
||||
struct object_list *p; |
||||
|
||||
while ((p = *pp) != NULL) { |
||||
if (p->item == target) |
||||
return; |
||||
pp = &p->next; |
||||
} |
||||
|
||||
target->used = 1; |
||||
p = malloc(sizeof(*p)); |
||||
p->item = target; |
||||
p->next = NULL; |
||||
*pp = p; |
||||
} |
||||
|
||||
void mark_reachable(struct object *obj, unsigned int mask) |
||||
{ |
||||
struct object_list *p = obj->refs; |
||||
|
||||
/* If we've been here already, don't bother */ |
||||
if (obj->flags & mask) |
||||
return; |
||||
obj->flags |= mask; |
||||
while (p) { |
||||
mark_reachable(p->item, mask); |
||||
p = p->next; |
||||
} |
||||
} |
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
#include "tree.h" |
||||
#include "blob.h" |
||||
#include "cache.h" |
||||
#include <stdlib.h> |
||||
|
||||
const char *tree_type = "tree"; |
||||
|
||||
struct tree *lookup_tree(unsigned char *sha1) |
||||
{ |
||||
struct object *obj = lookup_object(sha1); |
||||
if (!obj) { |
||||
struct tree *ret = malloc(sizeof(struct tree)); |
||||
memset(ret, 0, sizeof(struct tree)); |
||||
created_object(sha1, &ret->object); |
||||
return ret; |
||||
} |
||||
if (obj->parsed && obj->type != tree_type) { |
||||
error("Object %s is a %s, not a tree", |
||||
sha1_to_hex(sha1), obj->type); |
||||
return NULL; |
||||
} |
||||
return (struct tree *) obj; |
||||
} |
||||
|
||||
int parse_tree(struct tree *item) |
||||
{ |
||||
char type[20]; |
||||
void *buffer, *bufptr; |
||||
unsigned long size; |
||||
if (item->object.parsed) |
||||
return 0; |
||||
item->object.parsed = 1; |
||||
item->object.type = tree_type; |
||||
buffer = bufptr = read_sha1_file(item->object.sha1, type, &size); |
||||
if (!buffer) |
||||
return error("Could not read %s", |
||||
sha1_to_hex(item->object.sha1)); |
||||
if (strcmp(type, tree_type)) |
||||
return error("Object %s not a tree", |
||||
sha1_to_hex(item->object.sha1)); |
||||
while (size) { |
||||
struct object *obj; |
||||
int len = 1+strlen(bufptr); |
||||
unsigned char *file_sha1 = bufptr + len; |
||||
char *path = strchr(bufptr, ' '); |
||||
unsigned int mode; |
||||
if (size < len + 20 || !path || |
||||
sscanf(bufptr, "%o", &mode) != 1) |
||||
return -1; |
||||
|
||||
/* Warn about trees that don't do the recursive thing.. */ |
||||
if (strchr(path, '/')) { |
||||
item->has_full_path = 1; |
||||
} |
||||
|
||||
bufptr += len + 20; |
||||
size -= len + 20; |
||||
|
||||
if (S_ISDIR(mode)) { |
||||
obj = &lookup_tree(file_sha1)->object; |
||||
} else { |
||||
obj = &lookup_blob(file_sha1)->object; |
||||
} |
||||
add_ref(&item->object, obj); |
||||
} |
||||
return 0; |
||||
} |
Loading…
Reference in new issue