Merge the new object model thing from Daniel Barkalow
[git.git] / commit.c
1 #include "commit.h"
2 #include "cache.h"
3 #include <string.h>
4
5 const char *commit_type = "commit";
6
7 struct commit *lookup_commit(unsigned char *sha1)
8 {
9         struct object *obj = lookup_object(sha1);
10         if (!obj) {
11                 struct commit *ret = malloc(sizeof(struct commit));
12                 memset(ret, 0, sizeof(struct commit));
13                 created_object(sha1, &ret->object);
14                 return ret;
15         }
16         if (obj->parsed && obj->type != commit_type) {
17                 error("Object %s is a %s, not a commit", 
18                       sha1_to_hex(sha1), obj->type);
19                 return NULL;
20         }
21         return (struct commit *) obj;
22 }
23
24 static unsigned long parse_commit_date(const char *buf)
25 {
26         unsigned long date;
27
28         if (memcmp(buf, "author", 6))
29                 return 0;
30         while (*buf++ != '\n')
31                 /* nada */;
32         if (memcmp(buf, "committer", 9))
33                 return 0;
34         while (*buf++ != '>')
35                 /* nada */;
36         date = strtoul(buf, NULL, 10);
37         if (date == ULONG_MAX)
38                 date = 0;
39         return date;
40 }
41
42 int parse_commit(struct commit *item)
43 {
44         char type[20];
45         void * buffer, *bufptr;
46         unsigned long size;
47         unsigned char parent[20];
48         if (item->object.parsed)
49                 return 0;
50         item->object.parsed = 1;
51         buffer = bufptr = read_sha1_file(item->object.sha1, type, &size);
52         if (!buffer)
53                 return error("Could not read %s",
54                              sha1_to_hex(item->object.sha1));
55         if (strcmp(type, commit_type))
56                 return error("Object %s not a commit",
57                              sha1_to_hex(item->object.sha1));
58         item->object.type = commit_type;
59         get_sha1_hex(bufptr + 5, parent);
60         item->tree = lookup_tree(parent);
61         add_ref(&item->object, &item->tree->object);
62         bufptr += 46; /* "tree " + "hex sha1" + "\n" */
63         while (!memcmp(bufptr, "parent ", 7) &&
64                !get_sha1_hex(bufptr + 7, parent)) {
65                 struct commit_list *new_parent = 
66                         malloc(sizeof(struct commit_list));
67                 new_parent->next = item->parents;
68                 new_parent->item = lookup_commit(parent);
69                 add_ref(&item->object, &new_parent->item->object);
70                 item->parents = new_parent;
71                 bufptr += 48;
72         }
73         item->date = parse_commit_date(bufptr);
74         free(buffer);
75         return 0;
76 }
77
78 void free_commit_list(struct commit_list *list)
79 {
80         while (list) {
81                 struct commit_list *temp = list;
82                 list = temp->next;
83                 free(temp);
84         }
85 }