зеркало из https://github.com/microsoft/git.git
Merge branch 'jk/commit-buffer-length'
Move "commit->buffer" out of the in-core commit object and keep track of their lengths. Use this to optimize the code paths to validate GPG signatures in commit objects. * jk/commit-buffer-length: reuse cached commit buffer when parsing signatures commit: record buffer length in cache commit: convert commit->buffer to a slab commit-slab: provide a static initializer use get_commit_buffer everywhere convert logmsg_reencode to get_commit_buffer use get_commit_buffer to avoid duplicate code use get_cached_commit_buffer where appropriate provide helpers to access the commit buffer provide a helper to set the commit buffer provide a helper to free commit buffer sequencer: use logmsg_reencode in get_message logmsg_reencode: return const buffer do not create "struct commit" with xcalloc commit: push commit_index update into alloc_commit_node alloc: include any-object allocations in alloc_report replace dangerous uses of strbuf_attach commit_tree: take a pointer/len pair rather than a const strbuf
This commit is contained in:
Коммит
8061ae8b46
23
alloc.c
23
alloc.c
|
@ -47,23 +47,32 @@ union any_object {
|
|||
|
||||
DEFINE_ALLOCATOR(blob, struct blob)
|
||||
DEFINE_ALLOCATOR(tree, struct tree)
|
||||
DEFINE_ALLOCATOR(commit, struct commit)
|
||||
DEFINE_ALLOCATOR(raw_commit, struct commit)
|
||||
DEFINE_ALLOCATOR(tag, struct tag)
|
||||
DEFINE_ALLOCATOR(object, union any_object)
|
||||
|
||||
void *alloc_commit_node(void)
|
||||
{
|
||||
static int commit_count;
|
||||
struct commit *c = alloc_raw_commit_node();
|
||||
c->index = commit_count++;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void report(const char *name, unsigned int count, size_t size)
|
||||
{
|
||||
fprintf(stderr, "%10s: %8u (%"PRIuMAX" kB)\n",
|
||||
name, count, (uintmax_t) size);
|
||||
}
|
||||
|
||||
#define REPORT(name) \
|
||||
report(#name, name##_allocs, name##_allocs * sizeof(struct name) >> 10)
|
||||
#define REPORT(name, type) \
|
||||
report(#name, name##_allocs, name##_allocs * sizeof(type) >> 10)
|
||||
|
||||
void alloc_report(void)
|
||||
{
|
||||
REPORT(blob);
|
||||
REPORT(tree);
|
||||
REPORT(commit);
|
||||
REPORT(tag);
|
||||
REPORT(blob, struct blob);
|
||||
REPORT(tree, struct tree);
|
||||
REPORT(raw_commit, struct commit);
|
||||
REPORT(tag, struct tag);
|
||||
REPORT(object, union any_object);
|
||||
}
|
||||
|
|
|
@ -1655,7 +1655,7 @@ static void get_commit_info(struct commit *commit,
|
|||
{
|
||||
int len;
|
||||
const char *subject, *encoding;
|
||||
char *message;
|
||||
const char *message;
|
||||
|
||||
commit_info_init(ret);
|
||||
|
||||
|
@ -1666,7 +1666,7 @@ static void get_commit_info(struct commit *commit,
|
|||
&ret->author_time, &ret->author_tz);
|
||||
|
||||
if (!detailed) {
|
||||
logmsg_free(message, commit);
|
||||
unuse_commit_buffer(commit, message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1680,7 +1680,7 @@ static void get_commit_info(struct commit *commit,
|
|||
else
|
||||
strbuf_addf(&ret->summary, "(%s)", sha1_to_hex(commit->object.sha1));
|
||||
|
||||
logmsg_free(message, commit);
|
||||
unuse_commit_buffer(commit, message);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2251,6 +2251,18 @@ static void append_merge_parents(struct commit_list **tail)
|
|||
strbuf_release(&line);
|
||||
}
|
||||
|
||||
/*
|
||||
* This isn't as simple as passing sb->buf and sb->len, because we
|
||||
* want to transfer ownership of the buffer to the commit (so we
|
||||
* must use detach).
|
||||
*/
|
||||
static void set_commit_buffer_from_strbuf(struct commit *c, struct strbuf *sb)
|
||||
{
|
||||
size_t len;
|
||||
void *buf = strbuf_detach(sb, &len);
|
||||
set_commit_buffer(c, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare a dummy commit that represents the work tree (or staged) item.
|
||||
* Note that annotating work tree item never works in the reverse.
|
||||
|
@ -2272,7 +2284,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
|
|||
struct strbuf msg = STRBUF_INIT;
|
||||
|
||||
time(&now);
|
||||
commit = xcalloc(1, sizeof(*commit));
|
||||
commit = alloc_commit_node();
|
||||
commit->object.parsed = 1;
|
||||
commit->date = now;
|
||||
commit->object.type = OBJ_COMMIT;
|
||||
|
@ -2299,7 +2311,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
|
|||
ident, ident, path,
|
||||
(!contents_from ? path :
|
||||
(!strcmp(contents_from, "-") ? "standard input" : contents_from)));
|
||||
commit->buffer = strbuf_detach(&msg, NULL);
|
||||
set_commit_buffer_from_strbuf(commit, &msg);
|
||||
|
||||
if (!contents_from || strcmp("-", contents_from)) {
|
||||
struct stat st;
|
||||
|
|
|
@ -123,8 +123,8 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix)
|
|||
die_errno("git commit-tree: failed to read");
|
||||
}
|
||||
|
||||
if (commit_tree(&buffer, tree_sha1, parents, commit_sha1,
|
||||
NULL, sign_commit)) {
|
||||
if (commit_tree(buffer.buf, buffer.len, tree_sha1, parents,
|
||||
commit_sha1, NULL, sign_commit)) {
|
||||
strbuf_release(&buffer);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1745,8 +1745,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
|||
append_merge_tag_headers(parents, &tail);
|
||||
}
|
||||
|
||||
if (commit_tree_extended(&sb, active_cache_tree->sha1, parents, sha1,
|
||||
author_ident.buf, sign_commit, extra)) {
|
||||
if (commit_tree_extended(sb.buf, sb.len, active_cache_tree->sha1,
|
||||
parents, sha1, author_ident.buf, sign_commit, extra)) {
|
||||
rollback_index_files();
|
||||
die(_("failed to write commit object"));
|
||||
}
|
||||
|
|
|
@ -282,6 +282,7 @@ static const char *find_encoding(const char *begin, const char *end)
|
|||
static void handle_commit(struct commit *commit, struct rev_info *rev)
|
||||
{
|
||||
int saved_output_format = rev->diffopt.output_format;
|
||||
const char *commit_buffer;
|
||||
const char *author, *author_end, *committer, *committer_end;
|
||||
const char *encoding, *message;
|
||||
char *reencoded = NULL;
|
||||
|
@ -291,7 +292,8 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
|
|||
rev->diffopt.output_format = DIFF_FORMAT_CALLBACK;
|
||||
|
||||
parse_commit_or_die(commit);
|
||||
author = strstr(commit->buffer, "\nauthor ");
|
||||
commit_buffer = get_commit_buffer(commit, NULL);
|
||||
author = strstr(commit_buffer, "\nauthor ");
|
||||
if (!author)
|
||||
die ("Could not find author in commit %s",
|
||||
sha1_to_hex(commit->object.sha1));
|
||||
|
@ -338,6 +340,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev)
|
|||
? strlen(message) : 0),
|
||||
reencoded ? reencoded : message ? message : "");
|
||||
free(reencoded);
|
||||
unuse_commit_buffer(commit, commit_buffer);
|
||||
|
||||
for (i = 0, p = commit->parents; p; p = p->next) {
|
||||
int mark = get_object_mark(&p->item->object);
|
||||
|
|
|
@ -230,12 +230,14 @@ static void add_branch_desc(struct strbuf *out, const char *name)
|
|||
static void record_person(int which, struct string_list *people,
|
||||
struct commit *commit)
|
||||
{
|
||||
const char *buffer;
|
||||
char *name_buf, *name, *name_end;
|
||||
struct string_list_item *elem;
|
||||
const char *field;
|
||||
|
||||
field = (which == 'a') ? "\nauthor " : "\ncommitter ";
|
||||
name = strstr(commit->buffer, field);
|
||||
buffer = get_commit_buffer(commit, NULL);
|
||||
name = strstr(buffer, field);
|
||||
if (!name)
|
||||
return;
|
||||
name += strlen(field);
|
||||
|
@ -247,6 +249,7 @@ static void record_person(int which, struct string_list *people,
|
|||
if (name_end < name)
|
||||
return;
|
||||
name_buf = xmemdupz(name, name_end - name + 1);
|
||||
unuse_commit_buffer(commit, buffer);
|
||||
|
||||
elem = string_list_lookup(people, name_buf);
|
||||
if (!elem) {
|
||||
|
|
|
@ -310,8 +310,7 @@ static int fsck_obj(struct object *obj)
|
|||
if (obj->type == OBJ_COMMIT) {
|
||||
struct commit *commit = (struct commit *) obj;
|
||||
|
||||
free(commit->buffer);
|
||||
commit->buffer = NULL;
|
||||
free_commit_buffer(commit);
|
||||
|
||||
if (!commit->parents && show_root)
|
||||
printf("root %s\n", sha1_to_hex(commit->object.sha1));
|
||||
|
|
|
@ -786,7 +786,8 @@ static void sha1_object(const void *data, struct object_entry *obj_entry,
|
|||
}
|
||||
if (obj->type == OBJ_COMMIT) {
|
||||
struct commit *commit = (struct commit *) obj;
|
||||
commit->buffer = NULL;
|
||||
if (detach_commit_buffer(commit, NULL) != data)
|
||||
die("BUG: parse_object_buffer transmogrified our buffer");
|
||||
}
|
||||
obj->flags |= FLAG_CHECKED;
|
||||
}
|
||||
|
|
|
@ -347,8 +347,7 @@ static int cmd_log_walk(struct rev_info *rev)
|
|||
rev->max_count++;
|
||||
if (!rev->reflog_info) {
|
||||
/* we allow cycles in reflog ancestry */
|
||||
free(commit->buffer);
|
||||
commit->buffer = NULL;
|
||||
free_commit_buffer(commit);
|
||||
}
|
||||
free_commit_list(commit->parents);
|
||||
commit->parents = NULL;
|
||||
|
@ -925,9 +924,12 @@ static void make_cover_letter(struct rev_info *rev, int use_stdout,
|
|||
log_write_email_headers(rev, head, &pp.subject, &pp.after_subject,
|
||||
&need_8bit_cte);
|
||||
|
||||
for (i = 0; !need_8bit_cte && i < nr; i++)
|
||||
if (has_non_ascii(list[i]->buffer))
|
||||
for (i = 0; !need_8bit_cte && i < nr; i++) {
|
||||
const char *buf = get_commit_buffer(list[i], NULL);
|
||||
if (has_non_ascii(buf))
|
||||
need_8bit_cte = 1;
|
||||
unuse_commit_buffer(list[i], buf);
|
||||
}
|
||||
|
||||
if (!branch_name)
|
||||
branch_name = find_branch_name(rev);
|
||||
|
@ -1528,8 +1530,7 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
|||
reopen_stdout(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
|
||||
die(_("Failed to create output files"));
|
||||
shown = log_tree_commit(&rev, commit);
|
||||
free(commit->buffer);
|
||||
commit->buffer = NULL;
|
||||
free_commit_buffer(commit);
|
||||
|
||||
/* We put one extra blank line between formatted
|
||||
* patches and this flag is used by log-tree code
|
||||
|
|
|
@ -852,8 +852,8 @@ static int merge_trivial(struct commit *head, struct commit_list *remoteheads)
|
|||
parent->next->item = remoteheads->item;
|
||||
parent->next->next = NULL;
|
||||
prepare_to_commit(remoteheads);
|
||||
if (commit_tree(&merge_msg, result_tree, parent, result_commit, NULL,
|
||||
sign_commit))
|
||||
if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parent,
|
||||
result_commit, NULL, sign_commit))
|
||||
die(_("failed to write commit object"));
|
||||
finish(head, remoteheads, result_commit, "In-index merge");
|
||||
drop_save();
|
||||
|
@ -877,8 +877,8 @@ static int finish_automerge(struct commit *head,
|
|||
commit_list_insert(head, &parents);
|
||||
strbuf_addch(&merge_msg, '\n');
|
||||
prepare_to_commit(remoteheads);
|
||||
if (commit_tree(&merge_msg, result_tree, parents, result_commit,
|
||||
NULL, sign_commit))
|
||||
if (commit_tree(merge_msg.buf, merge_msg.len, result_tree, parents,
|
||||
result_commit, NULL, sign_commit))
|
||||
die(_("failed to write commit object"));
|
||||
strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
|
||||
finish(head, remoteheads, result_commit, buf.buf);
|
||||
|
|
|
@ -93,7 +93,7 @@ static int reset_index(const unsigned char *sha1, int reset_type, int quiet)
|
|||
static void print_new_head_line(struct commit *commit)
|
||||
{
|
||||
const char *hex, *body;
|
||||
char *msg;
|
||||
const char *msg;
|
||||
|
||||
hex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
|
||||
printf(_("HEAD is now at %s"), hex);
|
||||
|
@ -109,7 +109,7 @@ static void print_new_head_line(struct commit *commit)
|
|||
}
|
||||
else
|
||||
printf("\n");
|
||||
logmsg_free(msg, commit);
|
||||
unuse_commit_buffer(commit, msg);
|
||||
}
|
||||
|
||||
static void update_index_from_diff(struct diff_queue_struct *q,
|
||||
|
|
|
@ -106,7 +106,7 @@ static void show_commit(struct commit *commit, void *data)
|
|||
else
|
||||
putchar('\n');
|
||||
|
||||
if (revs->verbose_header && commit->buffer) {
|
||||
if (revs->verbose_header && get_cached_commit_buffer(commit, NULL)) {
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct pretty_print_context ctx = {0};
|
||||
ctx.abbrev = revs->abbrev;
|
||||
|
@ -173,8 +173,7 @@ static void finish_commit(struct commit *commit, void *data)
|
|||
free_commit_list(commit->parents);
|
||||
commit->parents = NULL;
|
||||
}
|
||||
free(commit->buffer);
|
||||
commit->buffer = NULL;
|
||||
free_commit_buffer(commit);
|
||||
}
|
||||
|
||||
static void finish_object(struct object *obj,
|
||||
|
|
|
@ -117,4 +117,16 @@ static int stat_ ##slabname## realloc
|
|||
* catch because GCC silently parses it by default.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Statically initialize a commit slab named "var". Note that this
|
||||
* evaluates "stride" multiple times! Example:
|
||||
*
|
||||
* struct indegree indegrees = COMMIT_SLAB_INIT(1, indegrees);
|
||||
*
|
||||
*/
|
||||
#define COMMIT_SLAB_INIT(stride, var) { \
|
||||
COMMIT_SLAB_SIZE / sizeof(**((var).slab)) / (stride), \
|
||||
(stride), 0, NULL \
|
||||
}
|
||||
|
||||
#endif /* COMMIT_SLAB_H */
|
||||
|
|
131
commit.c
131
commit.c
|
@ -17,7 +17,6 @@ static struct commit_extra_header *read_commit_extra_header_lines(const char *bu
|
|||
int save_commit_buffer = 1;
|
||||
|
||||
const char *commit_type = "commit";
|
||||
static int commit_count;
|
||||
|
||||
static struct commit *check_commit(struct object *obj,
|
||||
const unsigned char *sha1,
|
||||
|
@ -64,7 +63,6 @@ struct commit *lookup_commit(const unsigned char *sha1)
|
|||
struct object *obj = lookup_object(sha1);
|
||||
if (!obj) {
|
||||
struct commit *c = alloc_commit_node();
|
||||
c->index = commit_count++;
|
||||
return create_object(sha1, OBJ_COMMIT, c);
|
||||
}
|
||||
if (!obj->type)
|
||||
|
@ -247,6 +245,76 @@ int unregister_shallow(const unsigned char *sha1)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct commit_buffer {
|
||||
void *buffer;
|
||||
unsigned long size;
|
||||
};
|
||||
define_commit_slab(buffer_slab, struct commit_buffer);
|
||||
static struct buffer_slab buffer_slab = COMMIT_SLAB_INIT(1, buffer_slab);
|
||||
|
||||
void set_commit_buffer(struct commit *commit, void *buffer, unsigned long size)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
v->buffer = buffer;
|
||||
v->size = size;
|
||||
}
|
||||
|
||||
const void *get_cached_commit_buffer(const struct commit *commit, unsigned long *sizep)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
if (sizep)
|
||||
*sizep = v->size;
|
||||
return v->buffer;
|
||||
}
|
||||
|
||||
const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep)
|
||||
{
|
||||
const void *ret = get_cached_commit_buffer(commit, sizep);
|
||||
if (!ret) {
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
ret = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
if (!ret)
|
||||
die("cannot read commit object %s",
|
||||
sha1_to_hex(commit->object.sha1));
|
||||
if (type != OBJ_COMMIT)
|
||||
die("expected commit for %s, got %s",
|
||||
sha1_to_hex(commit->object.sha1), typename(type));
|
||||
if (sizep)
|
||||
*sizep = size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void unuse_commit_buffer(const struct commit *commit, const void *buffer)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
if (v->buffer != buffer)
|
||||
free((void *)buffer);
|
||||
}
|
||||
|
||||
void free_commit_buffer(struct commit *commit)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
free(v->buffer);
|
||||
v->buffer = NULL;
|
||||
v->size = 0;
|
||||
}
|
||||
|
||||
const void *detach_commit_buffer(struct commit *commit, unsigned long *sizep)
|
||||
{
|
||||
struct commit_buffer *v = buffer_slab_at(&buffer_slab, commit);
|
||||
void *ret;
|
||||
|
||||
ret = v->buffer;
|
||||
if (sizep)
|
||||
*sizep = v->size;
|
||||
|
||||
v->buffer = NULL;
|
||||
v->size = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size)
|
||||
{
|
||||
const char *tail = buffer;
|
||||
|
@ -324,7 +392,7 @@ int parse_commit(struct commit *item)
|
|||
}
|
||||
ret = parse_commit_buffer(item, buffer, size);
|
||||
if (save_commit_buffer && !ret) {
|
||||
item->buffer = buffer;
|
||||
set_commit_buffer(item, buffer, size);
|
||||
return 0;
|
||||
}
|
||||
free(buffer);
|
||||
|
@ -539,22 +607,12 @@ static void record_author_date(struct author_date_slab *author_date,
|
|||
struct commit *commit)
|
||||
{
|
||||
const char *buf, *line_end, *ident_line;
|
||||
char *buffer = NULL;
|
||||
const char *buffer = get_commit_buffer(commit, NULL);
|
||||
struct ident_split ident;
|
||||
char *date_end;
|
||||
unsigned long date;
|
||||
|
||||
if (!commit->buffer) {
|
||||
unsigned long size;
|
||||
enum object_type type;
|
||||
buffer = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
if (!buffer)
|
||||
return;
|
||||
}
|
||||
|
||||
for (buf = commit->buffer ? commit->buffer : buffer;
|
||||
buf;
|
||||
buf = line_end + 1) {
|
||||
for (buf = buffer; buf; buf = line_end + 1) {
|
||||
line_end = strchrnul(buf, '\n');
|
||||
ident_line = skip_prefix(buf, "author ");
|
||||
if (!ident_line) {
|
||||
|
@ -575,7 +633,7 @@ static void record_author_date(struct author_date_slab *author_date,
|
|||
*(author_date_slab_at(author_date, commit)) = date;
|
||||
|
||||
fail_exit:
|
||||
free(buffer);
|
||||
unuse_commit_buffer(commit, buffer);
|
||||
}
|
||||
|
||||
static int compare_commits_by_author_date(const void *a_, const void *b_,
|
||||
|
@ -1080,17 +1138,14 @@ static int do_sign_commit(struct strbuf *buf, const char *keyid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int parse_signed_commit(const unsigned char *sha1,
|
||||
int parse_signed_commit(const struct commit *commit,
|
||||
struct strbuf *payload, struct strbuf *signature)
|
||||
{
|
||||
unsigned long size;
|
||||
enum object_type type;
|
||||
char *buffer = read_sha1_file(sha1, &type, &size);
|
||||
int in_signature, saw_signature = -1;
|
||||
char *line, *tail;
|
||||
|
||||
if (!buffer || type != OBJ_COMMIT)
|
||||
goto cleanup;
|
||||
unsigned long size;
|
||||
const char *buffer = get_commit_buffer(commit, &size);
|
||||
int in_signature, saw_signature = -1;
|
||||
const char *line, *tail;
|
||||
|
||||
line = buffer;
|
||||
tail = buffer + size;
|
||||
|
@ -1098,7 +1153,7 @@ int parse_signed_commit(const unsigned char *sha1,
|
|||
saw_signature = 0;
|
||||
while (line < tail) {
|
||||
const char *sig = NULL;
|
||||
char *next = memchr(line, '\n', tail - line);
|
||||
const char *next = memchr(line, '\n', tail - line);
|
||||
|
||||
next = next ? next + 1 : tail;
|
||||
if (in_signature && line[0] == ' ')
|
||||
|
@ -1119,8 +1174,7 @@ int parse_signed_commit(const unsigned char *sha1,
|
|||
}
|
||||
line = next;
|
||||
}
|
||||
cleanup:
|
||||
free(buffer);
|
||||
unuse_commit_buffer(commit, buffer);
|
||||
return saw_signature;
|
||||
}
|
||||
|
||||
|
@ -1211,8 +1265,7 @@ void check_commit_signature(const struct commit* commit, struct signature_check
|
|||
|
||||
sigc->result = 'N';
|
||||
|
||||
if (parse_signed_commit(commit->object.sha1,
|
||||
&payload, &signature) <= 0)
|
||||
if (parse_signed_commit(commit, &payload, &signature) <= 0)
|
||||
goto out;
|
||||
status = verify_signed_buffer(payload.buf, payload.len,
|
||||
signature.buf, signature.len,
|
||||
|
@ -1257,11 +1310,9 @@ struct commit_extra_header *read_commit_extra_headers(struct commit *commit,
|
|||
{
|
||||
struct commit_extra_header *extra = NULL;
|
||||
unsigned long size;
|
||||
enum object_type type;
|
||||
char *buffer = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
if (buffer && type == OBJ_COMMIT)
|
||||
extra = read_commit_extra_header_lines(buffer, size, exclude);
|
||||
free(buffer);
|
||||
const char *buffer = get_commit_buffer(commit, &size);
|
||||
extra = read_commit_extra_header_lines(buffer, size, exclude);
|
||||
unuse_commit_buffer(commit, buffer);
|
||||
return extra;
|
||||
}
|
||||
|
||||
|
@ -1344,7 +1395,8 @@ void free_commit_extra_headers(struct commit_extra_header *extra)
|
|||
}
|
||||
}
|
||||
|
||||
int commit_tree(const struct strbuf *msg, const unsigned char *tree,
|
||||
int commit_tree(const char *msg, size_t msg_len,
|
||||
const unsigned char *tree,
|
||||
struct commit_list *parents, unsigned char *ret,
|
||||
const char *author, const char *sign_commit)
|
||||
{
|
||||
|
@ -1352,7 +1404,7 @@ int commit_tree(const struct strbuf *msg, const unsigned char *tree,
|
|||
int result;
|
||||
|
||||
append_merge_tag_headers(parents, &tail);
|
||||
result = commit_tree_extended(msg, tree, parents, ret,
|
||||
result = commit_tree_extended(msg, msg_len, tree, parents, ret,
|
||||
author, sign_commit, extra);
|
||||
free_commit_extra_headers(extra);
|
||||
return result;
|
||||
|
@ -1473,7 +1525,8 @@ static const char commit_utf8_warn[] =
|
|||
"You may want to amend it after fixing the message, or set the config\n"
|
||||
"variable i18n.commitencoding to the encoding your project uses.\n";
|
||||
|
||||
int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
|
||||
int commit_tree_extended(const char *msg, size_t msg_len,
|
||||
const unsigned char *tree,
|
||||
struct commit_list *parents, unsigned char *ret,
|
||||
const char *author, const char *sign_commit,
|
||||
struct commit_extra_header *extra)
|
||||
|
@ -1484,7 +1537,7 @@ int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
|
|||
|
||||
assert_sha1_type(tree, OBJ_TREE);
|
||||
|
||||
if (memchr(msg->buf, '\0', msg->len))
|
||||
if (memchr(msg, '\0', msg_len))
|
||||
return error("a NUL byte in commit log message not allowed.");
|
||||
|
||||
/* Not having i18n.commitencoding is the same as having utf-8 */
|
||||
|
@ -1523,7 +1576,7 @@ int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
|
|||
strbuf_addch(&buffer, '\n');
|
||||
|
||||
/* And add the comment */
|
||||
strbuf_addbuf(&buffer, msg);
|
||||
strbuf_add(&buffer, msg, msg_len);
|
||||
|
||||
/* And check the encoding */
|
||||
if (encoding_is_utf8 && !verify_utf8(&buffer))
|
||||
|
|
54
commit.h
54
commit.h
|
@ -20,7 +20,6 @@ struct commit {
|
|||
unsigned long date;
|
||||
struct commit_list *parents;
|
||||
struct tree *tree;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
extern int save_commit_buffer;
|
||||
|
@ -51,6 +50,44 @@ int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long s
|
|||
int parse_commit(struct commit *item);
|
||||
void parse_commit_or_die(struct commit *item);
|
||||
|
||||
/*
|
||||
* Associate an object buffer with the commit. The ownership of the
|
||||
* memory is handed over to the commit, and must be free()-able.
|
||||
*/
|
||||
void set_commit_buffer(struct commit *, void *buffer, unsigned long size);
|
||||
|
||||
/*
|
||||
* Get any cached object buffer associated with the commit. Returns NULL
|
||||
* if none. The resulting memory should not be freed.
|
||||
*/
|
||||
const void *get_cached_commit_buffer(const struct commit *, unsigned long *size);
|
||||
|
||||
/*
|
||||
* Get the commit's object contents, either from cache or by reading the object
|
||||
* from disk. The resulting memory should not be modified, and must be given
|
||||
* to unuse_commit_buffer when the caller is done.
|
||||
*/
|
||||
const void *get_commit_buffer(const struct commit *, unsigned long *size);
|
||||
|
||||
/*
|
||||
* Tell the commit subsytem that we are done with a particular commit buffer.
|
||||
* The commit and buffer should be the input and return value, respectively,
|
||||
* from an earlier call to get_commit_buffer. The buffer may or may not be
|
||||
* freed by this call; callers should not access the memory afterwards.
|
||||
*/
|
||||
void unuse_commit_buffer(const struct commit *, const void *buffer);
|
||||
|
||||
/*
|
||||
* Free any cached object buffer associated with the commit.
|
||||
*/
|
||||
void free_commit_buffer(struct commit *);
|
||||
|
||||
/*
|
||||
* Disassociate any cached object buffer from the commit, but do not free it.
|
||||
* The buffer (or NULL, if none) is returned.
|
||||
*/
|
||||
const void *detach_commit_buffer(struct commit *, unsigned long *sizep);
|
||||
|
||||
/* Find beginning and length of commit subject. */
|
||||
int find_commit_subject(const char *commit_buffer, const char **subject);
|
||||
|
||||
|
@ -115,10 +152,9 @@ struct userformat_want {
|
|||
|
||||
extern int has_non_ascii(const char *text);
|
||||
struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
|
||||
extern char *logmsg_reencode(const struct commit *commit,
|
||||
char **commit_encoding,
|
||||
const char *output_encoding);
|
||||
extern void logmsg_free(char *msg, const struct commit *commit);
|
||||
extern const char *logmsg_reencode(const struct commit *commit,
|
||||
char **commit_encoding,
|
||||
const char *output_encoding);
|
||||
extern void get_commit_format(const char *arg, struct rev_info *);
|
||||
extern const char *format_subject(struct strbuf *sb, const char *msg,
|
||||
const char *line_separator);
|
||||
|
@ -261,11 +297,13 @@ struct commit_extra_header {
|
|||
extern void append_merge_tag_headers(struct commit_list *parents,
|
||||
struct commit_extra_header ***tail);
|
||||
|
||||
extern int commit_tree(const struct strbuf *msg, const unsigned char *tree,
|
||||
extern int commit_tree(const char *msg, size_t msg_len,
|
||||
const unsigned char *tree,
|
||||
struct commit_list *parents, unsigned char *ret,
|
||||
const char *author, const char *sign_commit);
|
||||
|
||||
extern int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,
|
||||
extern int commit_tree_extended(const char *msg, size_t msg_len,
|
||||
const unsigned char *tree,
|
||||
struct commit_list *parents, unsigned char *ret,
|
||||
const char *author, const char *sign_commit,
|
||||
struct commit_extra_header *);
|
||||
|
@ -287,7 +325,7 @@ struct merge_remote_desc {
|
|||
*/
|
||||
struct commit *get_merge_parent(const char *name);
|
||||
|
||||
extern int parse_signed_commit(const unsigned char *sha1,
|
||||
extern int parse_signed_commit(const struct commit *commit,
|
||||
struct strbuf *message, struct strbuf *signature);
|
||||
extern void print_commit_list(struct commit_list *list,
|
||||
const char *format_cur,
|
||||
|
|
13
fsck.c
13
fsck.c
|
@ -276,9 +276,10 @@ static int fsck_ident(const char **ident, struct object *obj, fsck_error error_f
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fsck_commit(struct commit *commit, fsck_error error_func)
|
||||
static int fsck_commit_buffer(struct commit *commit, const char *buffer,
|
||||
fsck_error error_func)
|
||||
{
|
||||
const char *buffer = commit->buffer, *tmp;
|
||||
const char *tmp;
|
||||
unsigned char tree_sha1[20], sha1[20];
|
||||
struct commit_graft *graft;
|
||||
int parents = 0;
|
||||
|
@ -336,6 +337,14 @@ static int fsck_commit(struct commit *commit, fsck_error error_func)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int fsck_commit(struct commit *commit, fsck_error error_func)
|
||||
{
|
||||
const char *buffer = get_commit_buffer(commit, NULL);
|
||||
int ret = fsck_commit_buffer(commit, buffer, error_func);
|
||||
unuse_commit_buffer(commit, buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fsck_tag(struct tag *tag, fsck_error error_func)
|
||||
{
|
||||
struct object *tagged = tag->tagged;
|
||||
|
|
|
@ -376,7 +376,7 @@ static void show_signature(struct rev_info *opt, struct commit *commit)
|
|||
struct strbuf gpg_output = STRBUF_INIT;
|
||||
int status;
|
||||
|
||||
if (parse_signed_commit(commit->object.sha1, &payload, &signature) <= 0)
|
||||
if (parse_signed_commit(commit, &payload, &signature) <= 0)
|
||||
goto out;
|
||||
|
||||
status = verify_signed_buffer(payload.buf, payload.len,
|
||||
|
@ -588,7 +588,7 @@ void show_log(struct rev_info *opt)
|
|||
show_mergetag(opt, commit);
|
||||
}
|
||||
|
||||
if (!commit->buffer)
|
||||
if (!get_cached_commit_buffer(commit, NULL))
|
||||
return;
|
||||
|
||||
if (opt->show_notes) {
|
||||
|
|
|
@ -40,7 +40,7 @@ static struct tree *shift_tree_object(struct tree *one, struct tree *two,
|
|||
|
||||
static struct commit *make_virtual_commit(struct tree *tree, const char *comment)
|
||||
{
|
||||
struct commit *commit = xcalloc(1, sizeof(struct commit));
|
||||
struct commit *commit = alloc_commit_node();
|
||||
struct merge_remote_desc *desc = xmalloc(sizeof(*desc));
|
||||
|
||||
desc->name = comment;
|
||||
|
@ -190,9 +190,11 @@ static void output_commit_title(struct merge_options *o, struct commit *commit)
|
|||
printf(_("(bad commit)\n"));
|
||||
else {
|
||||
const char *title;
|
||||
int len = find_commit_subject(commit->buffer, &title);
|
||||
const char *msg = get_commit_buffer(commit, NULL);
|
||||
int len = find_commit_subject(msg, &title);
|
||||
if (len)
|
||||
printf("%.*s\n", len, title);
|
||||
unuse_commit_buffer(commit, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ int notes_cache_write(struct notes_cache *c)
|
|||
{
|
||||
unsigned char tree_sha1[20];
|
||||
unsigned char commit_sha1[20];
|
||||
struct strbuf msg = STRBUF_INIT;
|
||||
|
||||
if (!c || !c->tree.initialized || !c->tree.ref || !*c->tree.ref)
|
||||
return -1;
|
||||
|
@ -57,9 +56,8 @@ int notes_cache_write(struct notes_cache *c)
|
|||
|
||||
if (write_notes_tree(&c->tree, tree_sha1))
|
||||
return -1;
|
||||
strbuf_attach(&msg, c->validity,
|
||||
strlen(c->validity), strlen(c->validity) + 1);
|
||||
if (commit_tree(&msg, tree_sha1, NULL, commit_sha1, NULL, NULL) < 0)
|
||||
if (commit_tree(c->validity, strlen(c->validity), tree_sha1, NULL,
|
||||
commit_sha1, NULL, NULL) < 0)
|
||||
return -1;
|
||||
if (update_ref("update notes cache", c->tree.ref, commit_sha1, NULL,
|
||||
0, UPDATE_REFS_QUIET_ON_ERR) < 0)
|
||||
|
|
|
@ -644,7 +644,8 @@ int notes_merge(struct notes_merge_options *o,
|
|||
struct commit_list *parents = NULL;
|
||||
commit_list_insert(remote, &parents); /* LIFO order */
|
||||
commit_list_insert(local, &parents);
|
||||
create_notes_commit(local_tree, parents, &o->commit_msg,
|
||||
create_notes_commit(local_tree, parents,
|
||||
o->commit_msg.buf, o->commit_msg.len,
|
||||
result_sha1);
|
||||
}
|
||||
|
||||
|
@ -671,8 +672,8 @@ int notes_merge_commit(struct notes_merge_options *o,
|
|||
DIR *dir;
|
||||
struct dirent *e;
|
||||
struct strbuf path = STRBUF_INIT;
|
||||
char *msg = strstr(partial_commit->buffer, "\n\n");
|
||||
struct strbuf sb_msg = STRBUF_INIT;
|
||||
const char *buffer = get_commit_buffer(partial_commit, NULL);
|
||||
const char *msg = strstr(buffer, "\n\n");
|
||||
int baselen;
|
||||
|
||||
strbuf_addstr(&path, git_path(NOTES_MERGE_WORKTREE));
|
||||
|
@ -719,9 +720,9 @@ int notes_merge_commit(struct notes_merge_options *o,
|
|||
strbuf_setlen(&path, baselen);
|
||||
}
|
||||
|
||||
strbuf_attach(&sb_msg, msg, strlen(msg), strlen(msg) + 1);
|
||||
create_notes_commit(partial_tree, partial_commit->parents, &sb_msg,
|
||||
result_sha1);
|
||||
create_notes_commit(partial_tree, partial_commit->parents,
|
||||
msg, strlen(msg), result_sha1);
|
||||
unuse_commit_buffer(partial_commit, buffer);
|
||||
if (o->verbosity >= 4)
|
||||
printf("Finalized notes merge commit: %s\n",
|
||||
sha1_to_hex(result_sha1));
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
#include "notes-utils.h"
|
||||
|
||||
void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
|
||||
const struct strbuf *msg, unsigned char *result_sha1)
|
||||
const char *msg, size_t msg_len,
|
||||
unsigned char *result_sha1)
|
||||
{
|
||||
unsigned char tree_sha1[20];
|
||||
|
||||
|
@ -25,7 +26,7 @@ void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
|
|||
/* else: t->ref points to nothing, assume root/orphan commit */
|
||||
}
|
||||
|
||||
if (commit_tree(msg, tree_sha1, parents, result_sha1, NULL, NULL))
|
||||
if (commit_tree(msg, msg_len, tree_sha1, parents, result_sha1, NULL, NULL))
|
||||
die("Failed to commit notes tree to database");
|
||||
}
|
||||
|
||||
|
@ -46,7 +47,7 @@ void commit_notes(struct notes_tree *t, const char *msg)
|
|||
if (buf.buf[buf.len - 1] != '\n')
|
||||
strbuf_addch(&buf, '\n'); /* Make sure msg ends with newline */
|
||||
|
||||
create_notes_commit(t, NULL, &buf, commit_sha1);
|
||||
create_notes_commit(t, NULL, buf.buf, buf.len, commit_sha1);
|
||||
strbuf_insert(&buf, 0, "notes: ", 7); /* commit message starts at index 7 */
|
||||
update_ref(buf.buf, t->ref, commit_sha1, NULL, 0,
|
||||
UPDATE_REFS_DIE_ON_ERR);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* The resulting commit SHA1 is stored in result_sha1.
|
||||
*/
|
||||
void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
|
||||
const struct strbuf *msg, unsigned char *result_sha1);
|
||||
const char *msg, size_t msg_len, unsigned char *result_sha1);
|
||||
|
||||
void commit_notes(struct notes_tree *t, const char *msg);
|
||||
|
||||
|
|
4
object.c
4
object.c
|
@ -197,8 +197,8 @@ struct object *parse_object_buffer(const unsigned char *sha1, enum object_type t
|
|||
if (commit) {
|
||||
if (parse_commit_buffer(commit, buffer, size))
|
||||
return NULL;
|
||||
if (!commit->buffer) {
|
||||
commit->buffer = buffer;
|
||||
if (!get_cached_commit_buffer(commit, NULL)) {
|
||||
set_commit_buffer(commit, buffer, size);
|
||||
*eaten_p = 1;
|
||||
}
|
||||
obj = &commit->object;
|
||||
|
|
50
pretty.c
50
pretty.c
|
@ -606,29 +606,16 @@ static char *replace_encoding_header(char *buf, const char *encoding)
|
|||
return strbuf_detach(&tmp, NULL);
|
||||
}
|
||||
|
||||
char *logmsg_reencode(const struct commit *commit,
|
||||
char **commit_encoding,
|
||||
const char *output_encoding)
|
||||
const char *logmsg_reencode(const struct commit *commit,
|
||||
char **commit_encoding,
|
||||
const char *output_encoding)
|
||||
{
|
||||
static const char *utf8 = "UTF-8";
|
||||
const char *use_encoding;
|
||||
char *encoding;
|
||||
char *msg = commit->buffer;
|
||||
const char *msg = get_commit_buffer(commit, NULL);
|
||||
char *out;
|
||||
|
||||
if (!msg) {
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
|
||||
msg = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
if (!msg)
|
||||
die("Cannot read commit object %s",
|
||||
sha1_to_hex(commit->object.sha1));
|
||||
if (type != OBJ_COMMIT)
|
||||
die("Expected commit for '%s', got %s",
|
||||
sha1_to_hex(commit->object.sha1), typename(type));
|
||||
}
|
||||
|
||||
if (!output_encoding || !*output_encoding) {
|
||||
if (commit_encoding)
|
||||
*commit_encoding =
|
||||
|
@ -652,12 +639,13 @@ char *logmsg_reencode(const struct commit *commit,
|
|||
* Otherwise, we still want to munge the encoding header in the
|
||||
* result, which will be done by modifying the buffer. If we
|
||||
* are using a fresh copy, we can reuse it. But if we are using
|
||||
* the cached copy from commit->buffer, we need to duplicate it
|
||||
* to avoid munging commit->buffer.
|
||||
* the cached copy from get_commit_buffer, we need to duplicate it
|
||||
* to avoid munging the cached copy.
|
||||
*/
|
||||
out = msg;
|
||||
if (out == commit->buffer)
|
||||
out = xstrdup(out);
|
||||
if (msg == get_cached_commit_buffer(commit, NULL))
|
||||
out = xstrdup(msg);
|
||||
else
|
||||
out = (char *)msg;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
|
@ -667,8 +655,8 @@ char *logmsg_reencode(const struct commit *commit,
|
|||
* copy, we can free it.
|
||||
*/
|
||||
out = reencode_string(msg, output_encoding, use_encoding);
|
||||
if (out && msg != commit->buffer)
|
||||
free(msg);
|
||||
if (out)
|
||||
unuse_commit_buffer(commit, msg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -687,12 +675,6 @@ char *logmsg_reencode(const struct commit *commit,
|
|||
return out ? out : msg;
|
||||
}
|
||||
|
||||
void logmsg_free(char *msg, const struct commit *commit)
|
||||
{
|
||||
if (msg != commit->buffer)
|
||||
free(msg);
|
||||
}
|
||||
|
||||
static int mailmap_name(const char **email, size_t *email_len,
|
||||
const char **name, size_t *name_len)
|
||||
{
|
||||
|
@ -796,7 +778,7 @@ struct format_commit_context {
|
|||
struct signature_check signature_check;
|
||||
enum flush_type flush_type;
|
||||
enum trunc_type truncate;
|
||||
char *message;
|
||||
const char *message;
|
||||
char *commit_encoding;
|
||||
size_t width, indent1, indent2;
|
||||
int auto_color;
|
||||
|
@ -1536,7 +1518,7 @@ void format_commit_message(const struct commit *commit,
|
|||
}
|
||||
|
||||
free(context.commit_encoding);
|
||||
logmsg_free(context.message, commit);
|
||||
unuse_commit_buffer(commit, context.message);
|
||||
free(context.signature_check.gpg_output);
|
||||
free(context.signature_check.signer);
|
||||
}
|
||||
|
@ -1705,7 +1687,7 @@ void pretty_print_commit(struct pretty_print_context *pp,
|
|||
unsigned long beginning_of_body;
|
||||
int indent = 4;
|
||||
const char *msg;
|
||||
char *reencoded;
|
||||
const char *reencoded;
|
||||
const char *encoding;
|
||||
int need_8bit_cte = pp->need_8bit_cte;
|
||||
|
||||
|
@ -1772,7 +1754,7 @@ void pretty_print_commit(struct pretty_print_context *pp,
|
|||
if (pp->fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body)
|
||||
strbuf_addch(sb, '\n');
|
||||
|
||||
logmsg_free(reencoded, commit);
|
||||
unuse_commit_buffer(commit, reencoded);
|
||||
}
|
||||
|
||||
void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
|
||||
|
|
15
revision.c
15
revision.c
|
@ -2791,7 +2791,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
|
|||
{
|
||||
int retval;
|
||||
const char *encoding;
|
||||
char *message;
|
||||
const char *message;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
|
||||
if (!opt->grep_filter.pattern_list && !opt->grep_filter.header_list)
|
||||
|
@ -2833,14 +2833,21 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
|
|||
format_display_notes(commit->object.sha1, &buf, encoding, 1);
|
||||
}
|
||||
|
||||
/* Find either in the original commit message, or in the temporary */
|
||||
/*
|
||||
* Find either in the original commit message, or in the temporary.
|
||||
* Note that we cast away the constness of "message" here. It is
|
||||
* const because it may come from the cached commit buffer. That's OK,
|
||||
* because we know that it is modifiable heap memory, and that while
|
||||
* grep_buffer may modify it for speed, it will restore any
|
||||
* changes before returning.
|
||||
*/
|
||||
if (buf.len)
|
||||
retval = grep_buffer(&opt->grep_filter, buf.buf, buf.len);
|
||||
else
|
||||
retval = grep_buffer(&opt->grep_filter,
|
||||
message, strlen(message));
|
||||
(char *)message, strlen(message));
|
||||
strbuf_release(&buf);
|
||||
logmsg_free(message, commit);
|
||||
unuse_commit_buffer(commit, message);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
49
sequencer.c
49
sequencer.c
|
@ -116,39 +116,23 @@ static const char *action_name(const struct replay_opts *opts)
|
|||
return opts->action == REPLAY_REVERT ? "revert" : "cherry-pick";
|
||||
}
|
||||
|
||||
static char *get_encoding(const char *message);
|
||||
|
||||
struct commit_message {
|
||||
char *parent_label;
|
||||
const char *label;
|
||||
const char *subject;
|
||||
char *reencoded_message;
|
||||
const char *message;
|
||||
};
|
||||
|
||||
static int get_message(struct commit *commit, struct commit_message *out)
|
||||
{
|
||||
const char *encoding;
|
||||
const char *abbrev, *subject;
|
||||
int abbrev_len, subject_len;
|
||||
char *q;
|
||||
|
||||
if (!commit->buffer)
|
||||
return -1;
|
||||
encoding = get_encoding(commit->buffer);
|
||||
if (!encoding)
|
||||
encoding = "UTF-8";
|
||||
if (!git_commit_encoding)
|
||||
git_commit_encoding = "UTF-8";
|
||||
|
||||
out->reencoded_message = NULL;
|
||||
out->message = commit->buffer;
|
||||
if (same_encoding(encoding, git_commit_encoding))
|
||||
out->reencoded_message = reencode_string(commit->buffer,
|
||||
git_commit_encoding, encoding);
|
||||
if (out->reencoded_message)
|
||||
out->message = out->reencoded_message;
|
||||
|
||||
out->message = logmsg_reencode(commit, NULL, git_commit_encoding);
|
||||
abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
|
||||
abbrev_len = strlen(abbrev);
|
||||
|
||||
|
@ -167,29 +151,10 @@ static int get_message(struct commit *commit, struct commit_message *out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void free_message(struct commit_message *msg)
|
||||
static void free_message(struct commit *commit, struct commit_message *msg)
|
||||
{
|
||||
free(msg->parent_label);
|
||||
free(msg->reencoded_message);
|
||||
}
|
||||
|
||||
static char *get_encoding(const char *message)
|
||||
{
|
||||
const char *p = message, *eol;
|
||||
|
||||
while (*p && *p != '\n') {
|
||||
for (eol = p + 1; *eol && *eol != '\n'; eol++)
|
||||
; /* do nothing */
|
||||
if (starts_with(p, "encoding ")) {
|
||||
char *result = xmalloc(eol - 8 - p);
|
||||
strlcpy(result, p + 9, eol - 8 - p);
|
||||
return result;
|
||||
}
|
||||
p = eol;
|
||||
if (*p == '\n')
|
||||
p++;
|
||||
}
|
||||
return NULL;
|
||||
unuse_commit_buffer(commit, msg->message);
|
||||
}
|
||||
|
||||
static void write_cherry_pick_head(struct commit *commit, const char *pseudoref)
|
||||
|
@ -489,7 +454,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
|
|||
unsigned char head[20];
|
||||
struct commit *base, *next, *parent;
|
||||
const char *base_label, *next_label;
|
||||
struct commit_message msg = { NULL, NULL, NULL, NULL, NULL };
|
||||
struct commit_message msg = { NULL, NULL, NULL, NULL };
|
||||
char *defmsg = NULL;
|
||||
struct strbuf msgbuf = STRBUF_INIT;
|
||||
int res, unborn = 0, allow;
|
||||
|
@ -654,7 +619,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
|
|||
res = run_git_commit(defmsg, opts, allow);
|
||||
|
||||
leave:
|
||||
free_message(&msg);
|
||||
free_message(commit, &msg);
|
||||
free(defmsg);
|
||||
|
||||
return res;
|
||||
|
@ -701,10 +666,12 @@ static int format_todo(struct strbuf *buf, struct commit_list *todo_list,
|
|||
int subject_len;
|
||||
|
||||
for (cur = todo_list; cur; cur = cur->next) {
|
||||
const char *commit_buffer = get_commit_buffer(cur->item, NULL);
|
||||
sha1_abbrev = find_unique_abbrev(cur->item->object.sha1, DEFAULT_ABBREV);
|
||||
subject_len = find_commit_subject(cur->item->buffer, &subject);
|
||||
subject_len = find_commit_subject(commit_buffer, &subject);
|
||||
strbuf_addf(buf, "%s %s %.*s\n", action_str, sha1_abbrev,
|
||||
subject_len, subject);
|
||||
unuse_commit_buffer(cur->item, commit_buffer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
18
sha1_name.c
18
sha1_name.c
|
@ -862,27 +862,17 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1,
|
|||
commit_list_insert(l->item, &backup);
|
||||
}
|
||||
while (list) {
|
||||
char *p, *to_free = NULL;
|
||||
const char *p, *buf;
|
||||
struct commit *commit;
|
||||
enum object_type type;
|
||||
unsigned long size;
|
||||
int matches;
|
||||
|
||||
commit = pop_most_recent_commit(&list, ONELINE_SEEN);
|
||||
if (!parse_object(commit->object.sha1))
|
||||
continue;
|
||||
if (commit->buffer)
|
||||
p = commit->buffer;
|
||||
else {
|
||||
p = read_sha1_file(commit->object.sha1, &type, &size);
|
||||
if (!p)
|
||||
continue;
|
||||
to_free = p;
|
||||
}
|
||||
|
||||
p = strstr(p, "\n\n");
|
||||
buf = get_commit_buffer(commit, NULL);
|
||||
p = strstr(buf, "\n\n");
|
||||
matches = p && !regexec(®ex, p + 2, 0, NULL, 0);
|
||||
free(to_free);
|
||||
unuse_commit_buffer(commit, buf);
|
||||
|
||||
if (matches) {
|
||||
hashcpy(sha1, commit->object.sha1);
|
||||
|
|
Загрузка…
Ссылка в новой задаче