provide a helper to free commit buffer
authorJeff King <peff@peff.net>
Thu, 12 Jun 2014 22:05:37 +0000 (18:05 -0400)
committerJunio C Hamano <gitster@pobox.com>
Fri, 13 Jun 2014 19:07:47 +0000 (12:07 -0700)
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@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/fsck.c
builtin/index-pack.c
builtin/log.c
builtin/rev-list.c
commit.c
commit.h
index fc150c882122c53965fd246ad862e3a75d8768e2..8aadca160e857be8a87ec1f152e51eb6f51c90b5 100644 (file)
@@ -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));
index b9f6e12c0e91635eafd8510dc7cf20d6c3e58433..42551ce4ff65c170fffb88c5e9bb639bfc83fe91 100644 (file)
@@ -774,7 +774,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;
                }
index 39e883635279ad21f3ddd7b224f484b9b04700b0..226f8f2980036d332fbafe43eefb967d1b61b933 100644 (file)
@@ -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
index 9f92905379d1801a35bfad87bc05002d76dc23f4..e012ebe502cf57467fceb14ea3e01f30cd979313 100644 (file)
@@ -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,
index fbdc480ccf17b4d241e0a950e8dd44dfe9d684ce..11a05c1f24f541fa3495adc502cb292c3891fab4 100644 (file)
--- 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;
index 4df48cb68819bd914cfa7d087034775eba3a4c93..d72ed4334049b161116d945bfdbc08d59068ce1a 100644 (file)
--- 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);