Skip to content

Commit

Permalink
Merge branch 'jk/commit-buffer-length' into maint
Browse files Browse the repository at this point in the history
A handful of code paths had to read the commit object more than
once when showing header fields that are usually not parsed.  The
internal data structure to keep track of the contents of the commit
object has been updated to reduce the need for this double-reading,
and to allow the caller find the length of the object.

* 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
  • Loading branch information
Junio C Hamano committed Jul 16, 2014
2 parents 64630d8 + 218aa3a commit 5c18fde
Show file tree
Hide file tree
Showing 27 changed files with 284 additions and 197 deletions.
23 changes: 16 additions & 7 deletions alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
22 changes: 17 additions & 5 deletions builtin/blame.c
Original file line number Diff line number Diff line change
Expand Up @@ -1405,7 +1405,7 @@ static void get_commit_info(struct commit *commit,
{
int len;
const char *subject, *encoding;
char *message;
const char *message;

commit_info_init(ret);

Expand All @@ -1416,7 +1416,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;
}

Expand All @@ -1430,7 +1430,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);
}

/*
Expand Down Expand Up @@ -2005,6 +2005,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.
Expand All @@ -2026,7 +2038,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;
Expand All @@ -2053,7 +2065,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;
Expand Down
4 changes: 2 additions & 2 deletions builtin/commit-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions builtin/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1672,8 +1672,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"));
}
Expand Down
5 changes: 4 additions & 1 deletion builtin/fast-export.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,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;
Expand All @@ -288,7 +289,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));
Expand Down Expand Up @@ -335,6 +337,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);
Expand Down
5 changes: 4 additions & 1 deletion builtin/fmt-merge-msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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) {
Expand Down
3 changes: 1 addition & 2 deletions builtin/fsck.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
3 changes: 2 additions & 1 deletion builtin/index-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
13 changes: 7 additions & 6 deletions builtin/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,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;
Expand Down Expand Up @@ -915,9 +914,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);
Expand Down Expand Up @@ -1504,8 +1506,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
Expand Down
8 changes: 4 additions & 4 deletions builtin/merge.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions builtin/reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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,
Expand Down
5 changes: 2 additions & 3 deletions builtin/rev-list.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
12 changes: 12 additions & 0 deletions commit-slab.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Loading

0 comments on commit 5c18fde

Please sign in to comment.