]>
git.proxmox.com Git - libgit2.git/blob - src/commit_list.c
2 * Copyright (C) 2009-2012 the libgit2 contributors
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
8 #include "commit_list.h"
14 int git_commit_list_time_cmp(void *a
, void *b
)
16 git_commit_list_node
*commit_a
= (git_commit_list_node
*)a
;
17 git_commit_list_node
*commit_b
= (git_commit_list_node
*)b
;
19 return (commit_a
->time
< commit_b
->time
);
22 git_commit_list
*git_commit_list_insert(git_commit_list_node
*item
, git_commit_list
**list_p
)
24 git_commit_list
*new_list
= git__malloc(sizeof(git_commit_list
));
25 if (new_list
!= NULL
) {
26 new_list
->item
= item
;
27 new_list
->next
= *list_p
;
33 git_commit_list
*git_commit_list_insert_by_date(git_commit_list_node
*item
, git_commit_list
**list_p
)
35 git_commit_list
**pp
= list_p
;
38 while ((p
= *pp
) != NULL
) {
39 if (git_commit_list_time_cmp(p
->item
, item
) < 0)
45 return git_commit_list_insert(item
, pp
);
48 git_commit_list_node
*git_commit_list_alloc_node(git_revwalk
*walk
)
50 return (git_commit_list_node
*)git_pool_malloc(&walk
->commit_pool
, COMMIT_ALLOC
);
53 static int commit_error(git_commit_list_node
*commit
, const char *msg
)
55 char commit_oid
[GIT_OID_HEXSZ
+ 1];
56 git_oid_fmt(commit_oid
, &commit
->oid
);
57 commit_oid
[GIT_OID_HEXSZ
] = '\0';
59 giterr_set(GITERR_ODB
, "Failed to parse commit %s - %s", commit_oid
, msg
);
64 static git_commit_list_node
**alloc_parents(
65 git_revwalk
*walk
, git_commit_list_node
*commit
, size_t n_parents
)
67 if (n_parents
<= PARENTS_PER_COMMIT
)
68 return (git_commit_list_node
**)((char *)commit
+ sizeof(git_commit_list_node
));
70 return (git_commit_list_node
**)git_pool_malloc(
71 &walk
->commit_pool
, (uint32_t)(n_parents
* sizeof(git_commit_list_node
*)));
75 void git_commit_list_free(git_commit_list
**list_p
)
77 git_commit_list
*list
= *list_p
;
83 git_commit_list
*temp
= list
;
91 git_commit_list_node
*git_commit_list_pop(git_commit_list
**stack
)
93 git_commit_list
*top
= *stack
;
94 git_commit_list_node
*item
= top
? top
->item
: NULL
;
103 static int commit_quick_parse(git_revwalk
*walk
, git_commit_list_node
*commit
, git_rawobj
*raw
)
105 const size_t parent_len
= strlen("parent ") + GIT_OID_HEXSZ
+ 1;
106 unsigned char *buffer
= raw
->data
;
107 unsigned char *buffer_end
= buffer
+ raw
->len
;
108 unsigned char *parents_start
, *committer_start
;
112 buffer
+= strlen("tree ") + GIT_OID_HEXSZ
+ 1;
114 parents_start
= buffer
;
115 while (buffer
+ parent_len
< buffer_end
&& memcmp(buffer
, "parent ", strlen("parent ")) == 0) {
117 buffer
+= parent_len
;
120 commit
->parents
= alloc_parents(walk
, commit
, parents
);
121 GITERR_CHECK_ALLOC(commit
->parents
);
123 buffer
= parents_start
;
124 for (i
= 0; i
< parents
; ++i
) {
127 if (git_oid_fromstr(&oid
, (char *)buffer
+ strlen("parent ")) < 0)
130 commit
->parents
[i
] = commit_lookup(walk
, &oid
);
131 if (commit
->parents
[i
] == NULL
)
134 buffer
+= parent_len
;
137 commit
->out_degree
= (unsigned short)parents
;
139 if ((committer_start
= buffer
= memchr(buffer
, '\n', buffer_end
- buffer
)) == NULL
)
140 return commit_error(commit
, "object is corrupted");
144 if ((buffer
= memchr(buffer
, '\n', buffer_end
- buffer
)) == NULL
)
145 return commit_error(commit
, "object is corrupted");
147 /* Skip trailing spaces */
148 while (buffer
> committer_start
&& git__isspace(*buffer
))
151 /* Seek for the begining of the pack of digits */
152 while (buffer
> committer_start
&& git__isdigit(*buffer
))
155 /* Skip potential timezone offset */
156 if ((buffer
> committer_start
) && (*buffer
== '+' || *buffer
== '-')) {
159 while (buffer
> committer_start
&& git__isspace(*buffer
))
162 while (buffer
> committer_start
&& git__isdigit(*buffer
))
166 if ((buffer
== committer_start
) || (git__strtol32(&commit_time
, (char *)(buffer
+ 1), NULL
, 10) < 0))
167 return commit_error(commit
, "cannot parse commit time");
169 commit
->time
= (time_t)commit_time
;
174 int git_commit_list_parse(git_revwalk
*walk
, git_commit_list_node
*commit
)
182 if ((error
= git_odb_read(&obj
, walk
->odb
, &commit
->oid
)) < 0)
184 assert(obj
->raw
.type
== GIT_OBJ_COMMIT
);
186 error
= commit_quick_parse(walk
, commit
, &obj
->raw
);
187 git_odb_object_free(obj
);