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
;
30 static struct revision
**revs
;
31 static int nr_revs
, rev_allocs
;
33 static int find_rev(unsigned char *sha1
)
35 int first
= 0, last
= nr_revs
;
37 while (first
< last
) {
38 int next
= (first
+ last
) / 2;
39 struct revision
*rev
= revs
[next
];
42 cmp
= memcmp(sha1
, rev
->sha1
, 20);
54 static struct revision
*lookup_rev(unsigned char *sha1
)
56 int pos
= find_rev(sha1
);
64 if (rev_allocs
== nr_revs
) {
65 rev_allocs
= alloc_nr(rev_allocs
);
66 revs
= realloc(revs
, rev_allocs
* sizeof(struct revision
*));
68 n
= malloc(sizeof(struct revision
));
71 memcpy(n
->sha1
, sha1
, 20);
74 /* Insert it into the right place */
75 memmove(revs
+ pos
+ 1, revs
+ pos
, (nr_revs
- pos
) * sizeof(struct revision
*));
82 static struct revision
*add_relationship(struct revision
*rev
, unsigned char *needs
)
84 struct revision
*parent_rev
= lookup_rev(needs
);
85 struct parent
**pp
= &rev
->parent
, *p
;
87 while ((p
= *pp
) != NULL
) {
88 if (p
->parent
== parent_rev
)
93 p
= malloc(sizeof(*p
));
94 p
->parent
= parent_rev
;
100 static void mark_reachable(struct revision
*rev
, unsigned int mask
)
102 struct parent
*p
= rev
->parent
;
104 /* If we've been here already, don't bother */
105 if (rev
->flags
& mask
)
107 rev
->flags
|= mask
| USED
;
109 mark_reachable(p
->parent
, mask
);
114 static unsigned long parse_commit_date(const char *buf
)
118 if (memcmp(buf
, "author", 6))
120 while (*buf
++ != '\n')
122 if (memcmp(buf
, "committer", 9))
124 while (*buf
++ != '>')
126 date
= strtoul(buf
, NULL
, 10);
127 if (date
== ULONG_MAX
)
132 static int parse_commit(unsigned char *sha1
)
134 struct revision
*rev
= lookup_rev(sha1
);
136 if (!(rev
->flags
& SEEN
)) {
137 void *buffer
, *bufptr
;
140 unsigned char parent
[20];
143 buffer
= bufptr
= read_sha1_file(sha1
, type
, &size
);
144 if (!buffer
|| strcmp(type
, "commit"))
146 bufptr
+= 46; /* "tree " + "hex sha1" + "\n" */
147 while (!memcmp(bufptr
, "parent ", 7) && !get_sha1_hex(bufptr
+7, parent
)) {
148 add_relationship(rev
, parent
);
149 parse_commit(parent
);
150 bufptr
+= 48; /* "parent " + "hex sha1" + "\n" */
152 rev
->date
= parse_commit_date(bufptr
);
158 #endif /* REVISION_H */