On Thu, Jun 12, 2014 at 04:08:55PM -0400, Jeff King wrote: > So just putting in the safety check is probably the least-disruptive > thing. It doesn't automatically adapt to a change in the underlying > commit_buffer code, but it would at least notice it. Here is that commit with the check you suggested, and a better explanation in the commit message of what is going on. I don't know if it's easier for you to just replace patch 8 with this (there will be a minor textual conflict in the final commit then), or if you want me to re-post the whole 17-patch series. Arguably this could be broken into two commits (one to add the simple "free" and one for this more complicated "detach" case), but that makes it little more complicated for you to apply. We need some way of emailing patches coupled with rebase instructions. :) -- >8 -- Subject: provide a helper to free commit buffer This converts two lines into one at each caller. But more importantly, it abstracts the concept of freeing the buffer, which will make it easier to change later. Note that we also need to provide a "detach" mechanism for a tricky case in index-pack. We are passed a buffer for the object generated by processing the incoming pack.. If we are not using --strict, we just calculate the sha1 on that buffer and return, leaving the caller to free it. But if we are using --strict, we actually attach that buffer to an object, pass the object to the fsck functions, and then detach the buffer from the object again (so that the caller can free it as usual). In this case, we don't want to free the buffer ourselves, but just make sure it is no longer associated with the commit. Note that we are making the assumption here that the attach/detach process does not impact the buffer at all (e.g., it is never reallocated or modified). That holds true now, and we have no plans to change that. However, as we abstract the commit_buffer code, this dependency becomes less obvious. So when we detach, let's also make sure that we get back the same buffer that we gave to the commit_buffer code. Signed-off-by: Jeff King <peff@xxxxxxxx> --- builtin/fsck.c | 3 +-- builtin/index-pack.c | 3 ++- builtin/log.c | 6 ++---- builtin/rev-list.c | 3 +-- commit.c | 13 +++++++++++++ commit.h | 11 +++++++++++ 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/builtin/fsck.c b/builtin/fsck.c index fc150c8..8aadca1 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -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)); diff --git a/builtin/index-pack.c b/builtin/index-pack.c index 18f57de..3f88b12 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -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) != data) + die("BUG: parse_object_buffer transmogrified our buffer"); } obj->flags |= FLAG_CHECKED; } diff --git a/builtin/log.c b/builtin/log.c index 39e8836..226f8f2 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -349,8 +349,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; @@ -1508,8 +1507,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 diff --git a/builtin/rev-list.c b/builtin/rev-list.c index 9f92905..e012ebe 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -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, diff --git a/commit.c b/commit.c index fbdc480..11a05c1 100644 --- a/commit.c +++ b/commit.c @@ -245,6 +245,19 @@ int unregister_shallow(const unsigned char *sha1) return 0; } +void free_commit_buffer(struct commit *commit) +{ + free(commit->buffer); + commit->buffer = NULL; +} + +const void *detach_commit_buffer(struct commit *commit) +{ + void *ret = commit->buffer; + commit->buffer = NULL; + return ret; +} + int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size) { const char *tail = buffer; diff --git a/commit.h b/commit.h index 4df48cb..d72ed43 100644 --- a/commit.h +++ b/commit.h @@ -51,6 +51,17 @@ 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); +/* + * 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 *); + /* Find beginning and length of commit subject. */ int find_commit_subject(const char *commit_buffer, const char **subject); -- 2.0.0.566.gfe3e6b2 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html