5 * The low 16 bits of the "flags" field shows whether
6 * a commit is part of the path to the root for that
9 * Bit 16 is an internal flag that we've seen the
10 * definition for this rev, and not just seen it as
13 #define marked(rev) ((rev)->flags & 0xffff)
16 #define REACHABLE 0x40000
19 struct revision
*parent
;
25 unsigned char sha1
[20];
27 struct parent
*parent
;
31 static struct revision
**revs
;
32 static int nr_revs
, rev_allocs
;
34 static int find_rev(unsigned char *sha1
)
36 int first
= 0, last
= nr_revs
;
38 while (first
< last
) {
39 int next
= (first
+ last
) / 2;
40 struct revision
*rev
= revs
[next
];
43 cmp
= memcmp(sha1
, rev
->sha1
, 20);
55 static struct revision
*lookup_rev(unsigned char *sha1
, const char *tag
)
57 int pos
= find_rev(sha1
);
62 if (strcmp(n
->tag
, tag
))
63 error("expected tag %s on object %s: got %s", tag
, sha1_to_hex(sha1
), n
->tag
);
69 if (rev_allocs
== nr_revs
) {
70 rev_allocs
= alloc_nr(rev_allocs
);
71 revs
= realloc(revs
, rev_allocs
* sizeof(struct revision
*));
73 n
= malloc(sizeof(struct revision
) + strlen(tag
));
76 memcpy(n
->sha1
, sha1
, 20);
80 /* Insert it into the right place */
81 memmove(revs
+ pos
+ 1, revs
+ pos
, (nr_revs
- pos
) * sizeof(struct revision
*));
88 static struct revision
*add_relationship(struct revision
*rev
, unsigned char *needs
, const char *tag
)
90 struct revision
*parent_rev
= lookup_rev(needs
, tag
);
91 struct parent
**pp
= &rev
->parent
, *p
;
93 while ((p
= *pp
) != NULL
) {
94 if (p
->parent
== parent_rev
)
99 p
= malloc(sizeof(*p
));
100 p
->parent
= parent_rev
;
106 static void mark_reachable(struct revision
*rev
, unsigned int mask
)
108 struct parent
*p
= rev
->parent
;
110 /* If we've been here already, don't bother */
111 if (rev
->flags
& mask
)
113 rev
->flags
|= mask
| USED
;
115 mark_reachable(p
->parent
, mask
);
120 static unsigned long parse_commit_date(const char *buf
)
124 if (memcmp(buf
, "author", 6))
126 while (*buf
++ != '\n')
128 if (memcmp(buf
, "committer", 9))
130 while (*buf
++ != '>')
132 date
= strtoul(buf
, NULL
, 10);
133 if (date
== ULONG_MAX
)
138 static struct revision
* parse_commit(unsigned char *sha1
)
140 struct revision
*rev
= lookup_rev(sha1
, "commit");
142 if (!(rev
->flags
& SEEN
)) {
143 void *buffer
, *bufptr
;
146 unsigned char parent
[20];
149 buffer
= bufptr
= read_sha1_file(sha1
, type
, &size
);
150 if (!buffer
|| strcmp(type
, "commit"))
151 die("%s is not a commit object", sha1_to_hex(sha1
));
152 bufptr
+= 46; /* "tree " + "hex sha1" + "\n" */
153 while (!memcmp(bufptr
, "parent ", 7) && !get_sha1_hex(bufptr
+7, parent
)) {
154 add_relationship(rev
, parent
, "commit");
155 parse_commit(parent
);
156 bufptr
+= 48; /* "parent " + "hex sha1" + "\n" */
158 rev
->date
= parse_commit_date(bufptr
);
164 #endif /* REVISION_H */