diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 6cf5b86e15bd01d03aad4c3476a005923542a6f3..b859cb147c707d76685e999284d8cc647977e6a0 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -1907,13 +1907,19 @@ static void show_commit(struct commit *commit) commit->object.flags |= OBJECT_ADDED; } -static void show_object(struct object_array_entry *p) +static void show_object(struct object *obj, const struct name_path *path, const char *last) { - add_preferred_base_object(p->name); - add_object_entry(p->item->sha1, p->item->type, p->name, 0); - p->item->flags |= OBJECT_ADDED; - free((char *)p->name); - p->name = NULL; + char *name = path_name(path, last); + + add_preferred_base_object(name); + add_object_entry(obj->sha1, obj->type, name, 0); + obj->flags |= OBJECT_ADDED; + + /* + * We will have generated the hash from the name, + * but not saved a pointer to it - we can free it + */ + free((char *)name); } static void show_edge(struct commit *commit) diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 436afa45f5b7569551aa8301aee8a0752009a900..0af7cd94f99728e08379441061098e1966e36b73 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -168,27 +168,29 @@ static void finish_commit(struct commit *commit) commit->buffer = NULL; } -static void finish_object(struct object_array_entry *p) +static void finish_object(struct object *obj, const struct name_path *path, const char *name) { - if (p->item->type == OBJ_BLOB && !has_sha1_file(p->item->sha1)) - die("missing blob object '%s'", sha1_to_hex(p->item->sha1)); + if (obj->type == OBJ_BLOB && !has_sha1_file(obj->sha1)) + die("missing blob object '%s'", sha1_to_hex(obj->sha1)); } -static void show_object(struct object_array_entry *p) +static void show_object(struct object *obj, const struct name_path *path, const char *component) { + char *name = path_name(path, component); /* An object with name "foo\n0000000..." can be used to * confuse downstream "git pack-objects" very badly. */ - const char *ep = strchr(p->name, '\n'); + const char *ep = strchr(name, '\n'); - finish_object(p); + finish_object(obj, path, name); if (ep) { - printf("%s %.*s\n", sha1_to_hex(p->item->sha1), - (int) (ep - p->name), - p->name); + printf("%s %.*s\n", sha1_to_hex(obj->sha1), + (int) (ep - name), + name); } else - printf("%s %s\n", sha1_to_hex(p->item->sha1), p->name); + printf("%s %s\n", sha1_to_hex(obj->sha1), name); + free(name); } static void show_edge(struct commit *commit) diff --git a/list-objects.c b/list-objects.c index dd243c7c662c2f3fe9463b616bb00bed2cc503a7..30ded3d4dd9d41432eba317ccc8765746b7d5c95 100644 --- a/list-objects.c +++ b/list-objects.c @@ -10,7 +10,7 @@ static void process_blob(struct rev_info *revs, struct blob *blob, - struct object_array *p, + show_object_fn show, struct name_path *path, const char *name) { @@ -23,7 +23,7 @@ static void process_blob(struct rev_info *revs, if (obj->flags & (UNINTERESTING | SEEN)) return; obj->flags |= SEEN; - add_object(obj, p, path, name); + show(obj, path, name); } /* @@ -50,7 +50,7 @@ static void process_blob(struct rev_info *revs, */ static void process_gitlink(struct rev_info *revs, const unsigned char *sha1, - struct object_array *p, + show_object_fn show, struct name_path *path, const char *name) { @@ -59,7 +59,7 @@ static void process_gitlink(struct rev_info *revs, static void process_tree(struct rev_info *revs, struct tree *tree, - struct object_array *p, + show_object_fn show, struct name_path *path, const char *name) { @@ -77,7 +77,7 @@ static void process_tree(struct rev_info *revs, if (parse_tree(tree) < 0) die("bad tree object %s", sha1_to_hex(obj->sha1)); obj->flags |= SEEN; - add_object(obj, p, path, name); + show(obj, path, name); me.up = path; me.elem = name; me.elem_len = strlen(name); @@ -88,14 +88,14 @@ static void process_tree(struct rev_info *revs, if (S_ISDIR(entry.mode)) process_tree(revs, lookup_tree(entry.sha1), - p, &me, entry.path); + show, &me, entry.path); else if (S_ISGITLINK(entry.mode)) process_gitlink(revs, entry.sha1, - p, &me, entry.path); + show, &me, entry.path); else process_blob(revs, lookup_blob(entry.sha1), - p, &me, entry.path); + show, &me, entry.path); } free(tree->buffer); tree->buffer = NULL; @@ -134,16 +134,20 @@ void mark_edges_uninteresting(struct commit_list *list, } } +static void add_pending_tree(struct rev_info *revs, struct tree *tree) +{ + add_pending_object(revs, &tree->object, ""); +} + void traverse_commit_list(struct rev_info *revs, - void (*show_commit)(struct commit *), - void (*show_object)(struct object_array_entry *)) + show_commit_fn show_commit, + show_object_fn show_object) { int i; struct commit *commit; - struct object_array objects = { 0, 0, NULL }; while ((commit = get_revision(revs)) != NULL) { - process_tree(revs, commit->tree, &objects, NULL, ""); + add_pending_tree(revs, commit->tree); show_commit(commit); } for (i = 0; i < revs->pending.nr; i++) { @@ -154,25 +158,22 @@ void traverse_commit_list(struct rev_info *revs, continue; if (obj->type == OBJ_TAG) { obj->flags |= SEEN; - add_object_array(obj, name, &objects); + show_object(obj, NULL, name); continue; } if (obj->type == OBJ_TREE) { - process_tree(revs, (struct tree *)obj, &objects, + process_tree(revs, (struct tree *)obj, show_object, NULL, name); continue; } if (obj->type == OBJ_BLOB) { - process_blob(revs, (struct blob *)obj, &objects, + process_blob(revs, (struct blob *)obj, show_object, NULL, name); continue; } die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name); } - for (i = 0; i < objects.nr; i++) - show_object(&objects.objects[i]); - free(objects.objects); if (revs->pending.nr) { free(revs->pending.objects); revs->pending.nr = 0; diff --git a/list-objects.h b/list-objects.h index 0f41391ecc00eac324ea76de7654781c4fce094e..0b2de64301b59b5e27ca738242c92109332f9e07 100644 --- a/list-objects.h +++ b/list-objects.h @@ -2,7 +2,7 @@ #define LIST_OBJECTS_H typedef void (*show_commit_fn)(struct commit *); -typedef void (*show_object_fn)(struct object_array_entry *); +typedef void (*show_object_fn)(struct object *, const struct name_path *, const char *); typedef void (*show_edge_fn)(struct commit *); void traverse_commit_list(struct rev_info *revs, show_commit_fn, show_object_fn); diff --git a/revision.c b/revision.c index 34ee490ea0181091c375765141bd83e71ab2defe..d7d345bdd9c71eb0f8d77179b4af1b79049d054c 100644 --- a/revision.c +++ b/revision.c @@ -15,9 +15,9 @@ volatile show_early_output_fn_t show_early_output; -static char *path_name(struct name_path *path, const char *name) +char *path_name(const struct name_path *path, const char *name) { - struct name_path *p; + const struct name_path *p; char *n, *m; int nlen = strlen(name); int len = nlen + 1; diff --git a/revision.h b/revision.h index 66d211ac2e56be20fec686416dd6a2816b891239..bfe27071bfff3dda4a468844b0cc9195c67b5625 100644 --- a/revision.h +++ b/revision.h @@ -144,6 +144,8 @@ struct name_path { const char *elem; }; +char *path_name(const struct name_path *path, const char *name); + extern void add_object(struct object *obj, struct object_array *p, struct name_path *path, diff --git a/upload-pack.c b/upload-pack.c index 19c24db643c0bceb6e1b960d411d657d2feb0f32..b98b1d61c127de6368d24cc3c3b16a054724ed74 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -78,20 +78,22 @@ static void show_commit(struct commit *commit) commit->buffer = NULL; } -static void show_object(struct object_array_entry *p) +static void show_object(struct object *obj, const struct name_path *path, const char *component) { /* An object with name "foo\n0000000..." can be used to * confuse downstream git-pack-objects very badly. */ - const char *ep = strchr(p->name, '\n'); + const char *name = path_name(path, component); + const char *ep = strchr(name, '\n'); if (ep) { - fprintf(pack_pipe, "%s %.*s\n", sha1_to_hex(p->item->sha1), - (int) (ep - p->name), - p->name); + fprintf(pack_pipe, "%s %.*s\n", sha1_to_hex(obj->sha1), + (int) (ep - name), + name); } else fprintf(pack_pipe, "%s %s\n", - sha1_to_hex(p->item->sha1), p->name); + sha1_to_hex(obj->sha1), name); + free((char *)name); } static void show_edge(struct commit *commit)