#include "cache.h"
#include "tag.h"
#include "commit.h"
#include "pkt-line.h"
#include "utf8.h"
#include "diff.h"
#include "revision.h"
#include "notes.h"
int save_commit_buffer = 1;
const char *commit_type = "commit";
static struct commit *check_commit(struct object *obj,
const unsigned char *sha1,
int quiet)
{
if (obj->type != OBJ_COMMIT) {
if (!quiet)
error("Object %s is a %s, not a commit",
sha1_to_hex(sha1), typename(obj->type));
return NULL;
}
return (struct commit *) obj;
}
struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
int quiet)
{
struct object *obj = deref_tag(parse_object(sha1), NULL, 0);
if (!obj)
return NULL;
return check_commit(obj, sha1, quiet);
}
struct commit *lookup_commit_reference(const unsigned char *sha1)
{
return lookup_commit_reference_gently(sha1, 0);
}
struct commit *lookup_commit_or_die(const unsigned char *sha1, const char *ref_name)
{
struct commit *c = lookup_commit_reference(sha1);
if (!c)
die(_("could not parse %s"), ref_name);
if (hashcmp(sha1, c->object.sha1)) {
warning(_("%s %s is not a commit!"),
ref_name, sha1_to_hex(sha1));
}
return c;
}
struct commit *lookup_commit(const unsigned char *sha1)
{
struct object *obj = lookup_object(sha1);
if (!obj)
return create_object(sha1, OBJ_COMMIT, alloc_commit_node());
if (!obj->type)
obj->type = OBJ_COMMIT;
return check_commit(obj, sha1, 0);
}
struct commit *lookup_commit_reference_by_name(const char *name)
{
unsigned char sha1[20];
struct commit *commit;
if (get_sha1(name, sha1))
return NULL;
commit = lookup_commit_reference(sha1);
if (!commit || parse_commit(commit))
return NULL;
return commit;
}
static unsigned long parse_commit_date(const char *buf, const char *tail)
{
const char *dateptr;
if (buf + 6 >= tail)
return 0;
if (memcmp(buf, "author", 6))
return 0;
while (buf < tail && *buf++ != '\n')
/* nada */;
if (buf + 9 >= tail)
return 0;
if (memcmp(buf, "committer", 9))
return 0;
while (buf < tail && *buf++ != '>')
/* nada */;
if (buf >= tail)
return 0;
dateptr = buf;
while (buf < tail && *buf++ != '\n')
/* nada */;
if (buf >= tail)
return 0;
/* dateptr < buf && buf[-1] == '\n', so strtoul will stop at buf-1 */
return strtoul(dateptr, NULL, 10);
}
static struct commit_graft **commit_graft;
static int commit_graft_alloc, commit_graft_nr;
static int commit_graft_pos(const unsigned char *sha1)
{
int lo, hi;
lo = 0;
hi = commit_graft_nr;
while (lo < hi) {
int mi = (lo + hi) / 2;
struct commit_graft *graft = commit_graft[mi];
int cmp = hashcmp(sha1, graft->sha1);
if (!cmp)
return mi;
if (cmp < 0)
hi = mi;
else
lo = mi + 1;
}
return -lo - 1;
}
int register_commit_graft(struct commit_graft *graft, int ignore_dups)
{
int pos = commit_graft_pos(graft->sha1);
if (0 <= pos) {
if (ignore_dups)
free(graft);
else {
free(commit_graft[pos]);
commit_graft[pos] = graft;
}
return 1;
}
pos = -pos - 1;
if (commit_graft_alloc <= ++commit_graft_nr) {
commit_graft_alloc = alloc_nr(commit_graft_alloc);
commit_graft = xrealloc(commit_graft,
sizeof(*commit_graft) *
commit_graft_alloc);
}
if (pos < commit_graft_nr)
memmove(commit_graft + pos + 1,
commit_graft + pos,
(commit_graft_nr - pos - 1) *
sizeof(*commit_graft));
commit_graft[pos] = graft;
return 0;
}
struct commit_graft *read_graft_line(char *buf, int len)
{
/* The format is just "Commit Parent1 Parent2 ...\n" */
int i;
struct commit_graft *graft = NULL;
while (len && isspace(buf[len-1]))
buf[--len] = '\0';
if (buf[0] == '#' || buf[0] == '\0')
return NULL;
if ((len + 1) % 41)
goto bad_graft_data;
i = (len + 1) / 41 - 1;
graft = xmalloc(sizeof(*graft) + 20 * i);
graft->nr_parent = i;
if (get_sha1_hex(buf, graft->sha1))
goto bad_graft_data;
for (i = 40; i < len; i += 41) {
if (buf[i] != ' ')
goto bad_graft_data;
if (get_sha1_hex(buf + i + 1, graft->parent[i/41]))
goto bad_graft_data;
}
return graft;
bad_graft_data:
|