From 1b9b5c695e34051c80c9240fdb22e7c89ff0fd5f Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 16 Oct 2018 16:35:32 -0700 Subject: sha1_file: allow read_object to read objects in arbitrary repositories Allow read_object (a file local functon in sha1_file) to handle arbitrary repositories by passing the repository down to oid_object_info_extended. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/sha1-file.c b/sha1-file.c index dd0b6aa..b8ce21c 100644 --- a/sha1-file.c +++ b/sha1-file.c @@ -1361,7 +1361,9 @@ int oid_object_info(struct repository *r, return type; } -static void *read_object(const unsigned char *sha1, enum object_type *type, +static void *read_object(struct repository *r, + const unsigned char *sha1, + enum object_type *type, unsigned long *size) { struct object_id oid; @@ -1373,7 +1375,7 @@ static void *read_object(const unsigned char *sha1, enum object_type *type, hashcpy(oid.hash, sha1); - if (oid_object_info_extended(the_repository, &oid, &oi, 0) < 0) + if (oid_object_info_extended(r, &oid, &oi, 0) < 0) return NULL; return content; } @@ -1414,7 +1416,7 @@ void *read_object_file_extended(const struct object_id *oid, lookup_replace_object(the_repository, oid) : oid; errno = 0; - data = read_object(repl->hash, type, size); + data = read_object(the_repository, repl->hash, type, size); if (data) return data; @@ -1755,7 +1757,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime) if (has_loose_object(oid)) return 0; - buf = read_object(oid->hash, &type, &len); + buf = read_object(the_repository, oid->hash, &type, &len); if (!buf) return error(_("cannot read sha1_file for %s"), oid_to_hex(oid)); hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %lu", type_name(type), len) + 1; -- cgit v0.10.2-6-g49f6 From 33b94066f27199071abaa4067d29a98bbbbdae11 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 16 Oct 2018 16:35:33 -0700 Subject: packfile: allow has_packed_and_bad to handle arbitrary repositories has_packed_and_bad is not widely used, so just migrate it all at once. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/packfile.c b/packfile.c index 841b361..bc2e0f5 100644 --- a/packfile.c +++ b/packfile.c @@ -1131,12 +1131,13 @@ void mark_bad_packed_object(struct packed_git *p, const unsigned char *sha1) p->num_bad_objects++; } -const struct packed_git *has_packed_and_bad(const unsigned char *sha1) +const struct packed_git *has_packed_and_bad(struct repository *r, + const unsigned char *sha1) { struct packed_git *p; unsigned i; - for (p = the_repository->objects->packed_git; p; p = p->next) + for (p = r->objects->packed_git; p; p = p->next) for (i = 0; i < p->num_bad_objects; i++) if (hasheq(sha1, p->bad_object_sha1 + the_hash_algo->rawsz * i)) diff --git a/packfile.h b/packfile.h index 4426257..7a62d72 100644 --- a/packfile.h +++ b/packfile.h @@ -146,7 +146,7 @@ extern int packed_object_info(struct repository *r, off_t offset, struct object_info *); extern void mark_bad_packed_object(struct packed_git *p, const unsigned char *sha1); -extern const struct packed_git *has_packed_and_bad(const unsigned char *sha1); +extern const struct packed_git *has_packed_and_bad(struct repository *r, const unsigned char *sha1); /* * Iff a pack file in the given repository contains the object named by sha1, diff --git a/sha1-file.c b/sha1-file.c index b8ce21c..856e000 100644 --- a/sha1-file.c +++ b/sha1-file.c @@ -1432,7 +1432,7 @@ void *read_object_file_extended(const struct object_id *oid, die(_("loose object %s (stored in %s) is corrupt"), oid_to_hex(repl), path); - if ((p = has_packed_and_bad(repl->hash)) != NULL) + if ((p = has_packed_and_bad(the_repository, repl->hash)) != NULL) die(_("packed object %s (stored in %s) is corrupt"), oid_to_hex(repl), p->pack_name); -- cgit v0.10.2-6-g49f6 From a3b72c89bdd10f8b22d7dae382f0ce9833e5d179 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:46 -0800 Subject: object-store: allow read_object_file_extended to read from any repo read_object_file_extended is not widely used, so migrate it all at once. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/object-store.h b/object-store.h index 63b7605..3d98a68 100644 --- a/object-store.h +++ b/object-store.h @@ -161,12 +161,13 @@ void sha1_file_name(struct repository *r, struct strbuf *buf, const unsigned cha void *map_sha1_file(struct repository *r, const unsigned char *sha1, unsigned long *size); -extern void *read_object_file_extended(const struct object_id *oid, +extern void *read_object_file_extended(struct repository *r, + const struct object_id *oid, enum object_type *type, unsigned long *size, int lookup_replace); static inline void *read_object_file(const struct object_id *oid, enum object_type *type, unsigned long *size) { - return read_object_file_extended(oid, type, size, 1); + return read_object_file_extended(the_repository, oid, type, size, 1); } /* Read and unpack an object file into memory, write memory to an object file */ diff --git a/sha1-file.c b/sha1-file.c index 856e000..c5b704a 100644 --- a/sha1-file.c +++ b/sha1-file.c @@ -1403,7 +1403,8 @@ int pretend_object_file(void *buf, unsigned long len, enum object_type type, * deal with them should arrange to call read_object() and give error * messages themselves. */ -void *read_object_file_extended(const struct object_id *oid, +void *read_object_file_extended(struct repository *r, + const struct object_id *oid, enum object_type *type, unsigned long *size, int lookup_replace) @@ -1413,10 +1414,10 @@ void *read_object_file_extended(const struct object_id *oid, const char *path; struct stat st; const struct object_id *repl = lookup_replace ? - lookup_replace_object(the_repository, oid) : oid; + lookup_replace_object(r, oid) : oid; errno = 0; - data = read_object(the_repository, repl->hash, type, size); + data = read_object(r, repl->hash, type, size); if (data) return data; @@ -1428,11 +1429,11 @@ void *read_object_file_extended(const struct object_id *oid, die(_("replacement %s not found for %s"), oid_to_hex(repl), oid_to_hex(oid)); - if (!stat_sha1_file(the_repository, repl->hash, &st, &path)) + if (!stat_sha1_file(r, repl->hash, &st, &path)) die(_("loose object %s (stored in %s) is corrupt"), oid_to_hex(repl), path); - if ((p = has_packed_and_bad(the_repository, repl->hash)) != NULL) + if ((p = has_packed_and_bad(r, repl->hash)) != NULL) die(_("packed object %s (stored in %s) is corrupt"), oid_to_hex(repl), p->pack_name); diff --git a/streaming.c b/streaming.c index d1e6b2d..c843a12 100644 --- a/streaming.c +++ b/streaming.c @@ -490,7 +490,7 @@ static struct stream_vtbl incore_vtbl = { static open_method_decl(incore) { - st->u.incore.buf = read_object_file_extended(oid, type, &st->size, 0); + st->u.incore.buf = read_object_file_extended(the_repository, oid, type, &st->size, 0); st->u.incore.read_ptr = 0; st->vtbl = &incore_vtbl; -- cgit v0.10.2-6-g49f6 From afd69dcc21972d766211ac253af2c18384e93056 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:47 -0800 Subject: object-store: prepare read_object_file to deal with any repo As read_object_file is a widely used function (which is also regularly used in new code in flight between master..pu), changing its signature is painful is hard, as other series in flight rely on the original signature. It would burden the maintainer if we'd just change the signature. Introduce repo_read_object_file which takes the repository argument, and hide the original read_object_file as a macro behind NO_THE_REPOSITORY_COMPATIBILITY_MACROS, similar to e675765235 (diff.c: remove implicit dependency on the_index, 2018-09-21) Add a coccinelle patch to convert existing callers, but do not apply the resulting patch to keep the diff of this patch small. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/contrib/coccinelle/the_repository.pending.cocci b/contrib/coccinelle/the_repository.pending.cocci new file mode 100644 index 0000000..a7ac9e0 --- /dev/null +++ b/contrib/coccinelle/the_repository.pending.cocci @@ -0,0 +1,12 @@ +// This file is used for the ongoing refactoring of +// bringing the index or repository struct in all of +// our code base. + +@@ +expression E; +expression F; +expression G; +@@ +- read_object_file( ++ repo_read_object_file(the_repository, + E, F, G) diff --git a/object-store.h b/object-store.h index 3d98a68..00a6462 100644 --- a/object-store.h +++ b/object-store.h @@ -165,10 +165,16 @@ extern void *read_object_file_extended(struct repository *r, const struct object_id *oid, enum object_type *type, unsigned long *size, int lookup_replace); -static inline void *read_object_file(const struct object_id *oid, enum object_type *type, unsigned long *size) +static inline void *repo_read_object_file(struct repository *r, + const struct object_id *oid, + enum object_type *type, + unsigned long *size) { - return read_object_file_extended(the_repository, oid, type, size, 1); + return read_object_file_extended(r, oid, type, size, 1); } +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS +#define read_object_file(oid, type, size) repo_read_object_file(the_repository, oid, type, size) +#endif /* Read and unpack an object file into memory, write memory to an object file */ int oid_object_info(struct repository *r, const struct object_id *, unsigned long *); -- cgit v0.10.2-6-g49f6 From 9b45f499818f505f8f7797c6d8f63a3bdccfa95f Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:48 -0800 Subject: object-store: prepare has_{sha1, object}_file to handle any repo Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/contrib/coccinelle/the_repository.pending.cocci b/contrib/coccinelle/the_repository.pending.cocci index a7ac9e0..46f3a1b 100644 --- a/contrib/coccinelle/the_repository.pending.cocci +++ b/contrib/coccinelle/the_repository.pending.cocci @@ -10,3 +10,33 @@ expression G; - read_object_file( + repo_read_object_file(the_repository, E, F, G) + +@@ +expression E; +@@ +- has_sha1_file( ++ repo_has_sha1_file(the_repository, + E) + +@@ +expression E; +expression F; +@@ +- has_sha1_file_with_flags( ++ repo_has_sha1_file_with_flags(the_repository, + E) + +@@ +expression E; +@@ +- has_object_file( ++ repo_has_object_file(the_repository, + E) + +@@ +expression E; +expression F; +@@ +- has_object_file_with_flags( ++ repo_has_object_file_with_flags(the_repository, + E) diff --git a/object-store.h b/object-store.h index 00a6462..2b5e6ff 100644 --- a/object-store.h +++ b/object-store.h @@ -212,15 +212,27 @@ int read_loose_object(const char *path, * object_info. OBJECT_INFO_SKIP_CACHED is automatically set; pass * nonzero flags to also set other flags. */ -extern int has_sha1_file_with_flags(const unsigned char *sha1, int flags); -static inline int has_sha1_file(const unsigned char *sha1) +int repo_has_sha1_file_with_flags(struct repository *r, + const unsigned char *sha1, int flags); +static inline int repo_has_sha1_file(struct repository *r, + const unsigned char *sha1) { - return has_sha1_file_with_flags(sha1, 0); + return repo_has_sha1_file_with_flags(r, sha1, 0); } +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS +#define has_sha1_file_with_flags(sha1, flags) repo_has_sha1_file_with_flags(the_repository, sha1, flags) +#define has_sha1_file(sha1) repo_has_sha1_file(the_repository, sha1) +#endif + /* Same as the above, except for struct object_id. */ -extern int has_object_file(const struct object_id *oid); -extern int has_object_file_with_flags(const struct object_id *oid, int flags); +int repo_has_object_file(struct repository *r, const struct object_id *oid); +int repo_has_object_file_with_flags(struct repository *r, + const struct object_id *oid, int flags); +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS +#define has_object_file(oid) repo_has_object_file(the_repository, oid) +#define has_object_file_with_flags(oid, flags) repo_has_object_file_with_flags(the_repository, oid, flags) +#endif /* * Return true iff an alternate object database has a loose object diff --git a/sha1-file.c b/sha1-file.c index c5b704a..e77273c 100644 --- a/sha1-file.c +++ b/sha1-file.c @@ -1768,24 +1768,27 @@ int force_object_loose(const struct object_id *oid, time_t mtime) return ret; } -int has_sha1_file_with_flags(const unsigned char *sha1, int flags) +int repo_has_sha1_file_with_flags(struct repository *r, + const unsigned char *sha1, int flags) { struct object_id oid; if (!startup_info->have_repository) return 0; hashcpy(oid.hash, sha1); - return oid_object_info_extended(the_repository, &oid, NULL, + return oid_object_info_extended(r, &oid, NULL, flags | OBJECT_INFO_SKIP_CACHED) >= 0; } -int has_object_file(const struct object_id *oid) +int repo_has_object_file(struct repository *r, + const struct object_id *oid) { - return has_sha1_file(oid->hash); + return repo_has_sha1_file(r, oid->hash); } -int has_object_file_with_flags(const struct object_id *oid, int flags) +int repo_has_object_file_with_flags(struct repository *r, + const struct object_id *oid, int flags) { - return has_sha1_file_with_flags(oid->hash, flags); + return repo_has_sha1_file_with_flags(r, oid->hash, flags); } static void check_tree(const void *buf, size_t size) -- cgit v0.10.2-6-g49f6 From d1a69022650bbb6a56ebe93a28fe8b0e6a8d7fa7 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:49 -0800 Subject: object: parse_object to honor its repository argument In 8e4b0b6047 (object.c: allow parse_object to handle arbitrary repositories, 2018-06-28), we forgot to pass the repository down to the read_object_file. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/object.c b/object.c index e541605..003f870 100644 --- a/object.c +++ b/object.c @@ -259,8 +259,8 @@ struct object *parse_object(struct repository *r, const struct object_id *oid) if (obj && obj->parsed) return obj; - if ((obj && obj->type == OBJ_BLOB && has_object_file(oid)) || - (!obj && has_object_file(oid) && + if ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) || + (!obj && repo_has_object_file(r, oid) && oid_object_info(r, oid, NULL) == OBJ_BLOB)) { if (check_object_signature(repl, NULL, 0, NULL) < 0) { error(_("sha1 mismatch %s"), oid_to_hex(oid)); @@ -270,7 +270,7 @@ struct object *parse_object(struct repository *r, const struct object_id *oid) return lookup_object(r, oid->hash); } - buffer = read_object_file(oid, &type, &size); + buffer = repo_read_object_file(r, oid, &type, &size); if (buffer) { if (check_object_signature(repl, buffer, size, type_name(type)) < 0) { free(buffer); -- cgit v0.10.2-6-g49f6 From 9e5252abd1239215c36f86704e84ba06dc30583f Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:50 -0800 Subject: commit: allow parse_commit* to handle any repo Just like the previous commit, parse_commit and friends are used a lot and are found in new patches, so we cannot change their signature easily. Re-introduce these function prefixed with 'repo_' that take a repository argument and keep the original as a shallow macro. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/commit.c b/commit.c index dc8a39d..7a931d7 100644 --- a/commit.c +++ b/commit.c @@ -443,7 +443,10 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b return 0; } -int parse_commit_internal(struct commit *item, int quiet_on_missing, int use_commit_graph) +int repo_parse_commit_internal(struct repository *r, + struct commit *item, + int quiet_on_missing, + int use_commit_graph) { enum object_type type; void *buffer; @@ -454,9 +457,9 @@ int parse_commit_internal(struct commit *item, int quiet_on_missing, int use_com return -1; if (item->object.parsed) return 0; - if (use_commit_graph && parse_commit_in_graph(the_repository, item)) + if (use_commit_graph && parse_commit_in_graph(r, item)) return 0; - buffer = read_object_file(&item->object.oid, &type, &size); + buffer = repo_read_object_file(r, &item->object.oid, &type, &size); if (!buffer) return quiet_on_missing ? -1 : error("Could not read %s", @@ -467,18 +470,19 @@ int parse_commit_internal(struct commit *item, int quiet_on_missing, int use_com oid_to_hex(&item->object.oid)); } - ret = parse_commit_buffer(the_repository, item, buffer, size, 0); + ret = parse_commit_buffer(r, item, buffer, size, 0); if (save_commit_buffer && !ret) { - set_commit_buffer(the_repository, item, buffer, size); + set_commit_buffer(r, item, buffer, size); return 0; } free(buffer); return ret; } -int parse_commit_gently(struct commit *item, int quiet_on_missing) +int repo_parse_commit_gently(struct repository *r, + struct commit *item, int quiet_on_missing) { - return parse_commit_internal(item, quiet_on_missing, 1); + return repo_parse_commit_internal(r, item, quiet_on_missing, 1); } void parse_commit_or_die(struct commit *item) diff --git a/commit.h b/commit.h index 1d260d6..08935f9 100644 --- a/commit.h +++ b/commit.h @@ -79,12 +79,21 @@ struct commit *lookup_commit_reference_by_name(const char *name); struct commit *lookup_commit_or_die(const struct object_id *oid, const char *ref_name); int parse_commit_buffer(struct repository *r, struct commit *item, const void *buffer, unsigned long size, int check_graph); -int parse_commit_internal(struct commit *item, int quiet_on_missing, int use_commit_graph); -int parse_commit_gently(struct commit *item, int quiet_on_missing); -static inline int parse_commit(struct commit *item) +int repo_parse_commit_internal(struct repository *r, struct commit *item, + int quiet_on_missing, int use_commit_graph); +int repo_parse_commit_gently(struct repository *r, + struct commit *item, + int quiet_on_missing); +static inline int repo_parse_commit(struct repository *r, struct commit *item) { - return parse_commit_gently(item, 0); + return repo_parse_commit_gently(r, item, 0); } +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS +#define parse_commit_internal(item, quiet, use) repo_parse_commit_internal(the_repository, item, quiet, use) +#define parse_commit_gently(item, quiet) repo_parse_commit_gently(the_repository, item, quiet) +#define parse_commit(item) repo_parse_commit(the_repository, item) +#endif + void parse_commit_or_die(struct commit *item); struct buffer_slab; diff --git a/contrib/coccinelle/the_repository.pending.cocci b/contrib/coccinelle/the_repository.pending.cocci index 46f3a1b..b185fe0 100644 --- a/contrib/coccinelle/the_repository.pending.cocci +++ b/contrib/coccinelle/the_repository.pending.cocci @@ -40,3 +40,27 @@ expression F; - has_object_file_with_flags( + repo_has_object_file_with_flags(the_repository, E) + +@@ +expression E; +expression F; +expression G; +@@ +- parse_commit_internal( ++ repo_parse_commit_internal(the_repository, + E, F, G) + +@@ +expression E; +expression F; +@@ +- parse_commit_gently( ++ repo_parse_commit_gently(the_repository, + E, F) + +@@ +expression E; +@@ +- parse_commit( ++ repo_parse_commit(the_repository, + E) -- cgit v0.10.2-6-g49f6 From c383830a91fcaf402db1051a9cec2eb93cdd6b78 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:51 -0800 Subject: commit-reach.c: allow paint_down_to_common to handle any repo As the function is file local and not widely used, migrate it all at once. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/commit-reach.c b/commit-reach.c index 9f79ce0..67c2e43 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -30,7 +30,8 @@ static int queue_has_nonstale(struct prio_queue *queue) } /* all input commits in one and twos[] must have been parsed! */ -static struct commit_list *paint_down_to_common(struct commit *one, int n, +static struct commit_list *paint_down_to_common(struct repository *r, + struct commit *one, int n, struct commit **twos, int min_generation) { @@ -83,7 +84,7 @@ static struct commit_list *paint_down_to_common(struct commit *one, int n, parents = parents->next; if ((p->object.flags & flags) == flags) continue; - if (parse_commit(p)) + if (repo_parse_commit(r, p)) return NULL; p->object.flags |= flags; prio_queue_put(&queue, p); @@ -116,7 +117,7 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co return NULL; } - list = paint_down_to_common(one, n, twos, 0); + list = paint_down_to_common(the_repository, one, n, twos, 0); while (list) { struct commit *commit = pop_commit(&list); @@ -187,8 +188,8 @@ static int remove_redundant(struct commit **array, int cnt) if (array[j]->generation < min_generation) min_generation = array[j]->generation; } - common = paint_down_to_common(array[i], filled, work, - min_generation); + common = paint_down_to_common(the_repository, array[i], filled, + work, min_generation); if (array[i]->object.flags & PARENT2) redundant[i] = 1; for (j = 0; j < filled; j++) @@ -322,7 +323,9 @@ int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit * if (commit->generation > min_generation) return ret; - bases = paint_down_to_common(commit, nr_reference, reference, commit->generation); + bases = paint_down_to_common(the_repository, commit, + nr_reference, reference, + commit->generation); if (commit->object.flags & PARENT2) ret = 1; clear_commit_marks(commit, all_flags); -- cgit v0.10.2-6-g49f6 From 18256a915c64ac9b6b7ecec4d4c22b7f6fcca507 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:52 -0800 Subject: commit-reach.c: allow merge_bases_many to handle any repo Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/commit-reach.c b/commit-reach.c index 67c2e43..a53b31e 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -95,7 +95,9 @@ static struct commit_list *paint_down_to_common(struct repository *r, return result; } -static struct commit_list *merge_bases_many(struct commit *one, int n, struct commit **twos) +static struct commit_list *merge_bases_many(struct repository *r, + struct commit *one, int n, + struct commit **twos) { struct commit_list *list = NULL; struct commit_list *result = NULL; @@ -110,14 +112,14 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co return commit_list_insert(one, &result); } - if (parse_commit(one)) + if (repo_parse_commit(r, one)) return NULL; for (i = 0; i < n; i++) { - if (parse_commit(twos[i])) + if (repo_parse_commit(r, twos[i])) return NULL; } - list = paint_down_to_common(the_repository, one, n, twos, 0); + list = paint_down_to_common(r, one, n, twos, 0); while (list) { struct commit *commit = pop_commit(&list); @@ -224,7 +226,7 @@ static struct commit_list *get_merge_bases_many_0(struct commit *one, struct commit_list *result; int cnt, i; - result = merge_bases_many(one, n, twos); + result = merge_bases_many(the_repository, one, n, twos); for (i = 0; i < n; i++) { if (one == twos[i]) return result; -- cgit v0.10.2-6-g49f6 From ed8a0e3ac5e9c2c625bb86f0de5a82f91075e720 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:53 -0800 Subject: commit-reach.c: allow remove_redundant to handle any repo Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/commit-reach.c b/commit-reach.c index a53b31e..8101583 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -156,7 +156,7 @@ struct commit_list *get_octopus_merge_bases(struct commit_list *in) return ret; } -static int remove_redundant(struct commit **array, int cnt) +static int remove_redundant(struct repository *r, struct commit **array, int cnt) { /* * Some commit in the array may be an ancestor of @@ -174,7 +174,7 @@ static int remove_redundant(struct commit **array, int cnt) ALLOC_ARRAY(filled_index, cnt - 1); for (i = 0; i < cnt; i++) - parse_commit(array[i]); + repo_parse_commit(r, array[i]); for (i = 0; i < cnt; i++) { struct commit_list *common; uint32_t min_generation = array[i]->generation; @@ -190,7 +190,7 @@ static int remove_redundant(struct commit **array, int cnt) if (array[j]->generation < min_generation) min_generation = array[j]->generation; } - common = paint_down_to_common(the_repository, array[i], filled, + common = paint_down_to_common(r, array[i], filled, work, min_generation); if (array[i]->object.flags & PARENT2) redundant[i] = 1; @@ -249,7 +249,7 @@ static struct commit_list *get_merge_bases_many_0(struct commit *one, clear_commit_marks(one, all_flags); clear_commit_marks_many(n, twos, all_flags); - cnt = remove_redundant(rslt, cnt); + cnt = remove_redundant(the_repository, rslt, cnt); result = NULL; for (i = 0; i < cnt; i++) commit_list_insert_by_date(rslt[i], &result); @@ -370,7 +370,7 @@ struct commit_list *reduce_heads(struct commit_list *heads) p->item->object.flags &= ~STALE; } } - num_head = remove_redundant(array, num_head); + num_head = remove_redundant(the_repository, array, num_head); for (i = 0; i < num_head; i++) tail = &commit_list_insert(array[i], tail)->next; free(array); -- cgit v0.10.2-6-g49f6 From f28e87f526949c547308c16426cc4607464c5f37 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:54 -0800 Subject: commit-reach.c: allow get_merge_bases_many_0 to handle any repo Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/commit-reach.c b/commit-reach.c index 8101583..b3b1f62 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -216,7 +216,8 @@ static int remove_redundant(struct repository *r, struct commit **array, int cnt return filled; } -static struct commit_list *get_merge_bases_many_0(struct commit *one, +static struct commit_list *get_merge_bases_many_0(struct repository *r, + struct commit *one, int n, struct commit **twos, int cleanup) @@ -226,7 +227,7 @@ static struct commit_list *get_merge_bases_many_0(struct commit *one, struct commit_list *result; int cnt, i; - result = merge_bases_many(the_repository, one, n, twos); + result = merge_bases_many(r, one, n, twos); for (i = 0; i < n; i++) { if (one == twos[i]) return result; @@ -249,7 +250,7 @@ static struct commit_list *get_merge_bases_many_0(struct commit *one, clear_commit_marks(one, all_flags); clear_commit_marks_many(n, twos, all_flags); - cnt = remove_redundant(the_repository, rslt, cnt); + cnt = remove_redundant(r, rslt, cnt); result = NULL; for (i = 0; i < cnt; i++) commit_list_insert_by_date(rslt[i], &result); @@ -261,19 +262,19 @@ struct commit_list *get_merge_bases_many(struct commit *one, int n, struct commit **twos) { - return get_merge_bases_many_0(one, n, twos, 1); + return get_merge_bases_many_0(the_repository, one, n, twos, 1); } struct commit_list *get_merge_bases_many_dirty(struct commit *one, int n, struct commit **twos) { - return get_merge_bases_many_0(one, n, twos, 0); + return get_merge_bases_many_0(the_repository, one, n, twos, 0); } struct commit_list *get_merge_bases(struct commit *one, struct commit *two) { - return get_merge_bases_many_0(one, 1, &two, 1); + return get_merge_bases_many_0(the_repository, one, 1, &two, 1); } /* -- cgit v0.10.2-6-g49f6 From 21a9651ba3fb350f48a53bf885a225bf6b71cac3 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:55 -0800 Subject: commit-reach: prepare get_merge_bases to handle any repo Similarly to previous patches, the get_merge_base functions are used often in the code base, which makes migrating them hard. Implement the new functions, prefixed with 'repo_' and hide the old functions behind a wrapper macro. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/commit-reach.c b/commit-reach.c index b3b1f62..657a4e9 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -258,23 +258,27 @@ static struct commit_list *get_merge_bases_many_0(struct repository *r, return result; } -struct commit_list *get_merge_bases_many(struct commit *one, - int n, - struct commit **twos) +struct commit_list *repo_get_merge_bases_many(struct repository *r, + struct commit *one, + int n, + struct commit **twos) { - return get_merge_bases_many_0(the_repository, one, n, twos, 1); + return get_merge_bases_many_0(r, one, n, twos, 1); } -struct commit_list *get_merge_bases_many_dirty(struct commit *one, - int n, - struct commit **twos) +struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r, + struct commit *one, + int n, + struct commit **twos) { - return get_merge_bases_many_0(the_repository, one, n, twos, 0); + return get_merge_bases_many_0(r, one, n, twos, 0); } -struct commit_list *get_merge_bases(struct commit *one, struct commit *two) +struct commit_list *repo_get_merge_bases(struct repository *r, + struct commit *one, + struct commit *two) { - return get_merge_bases_many_0(the_repository, one, 1, &two, 1); + return get_merge_bases_many_0(r, one, 1, &two, 1); } /* diff --git a/commit-reach.h b/commit-reach.h index 7d313e2..52667d6 100644 --- a/commit-reach.h +++ b/commit-reach.h @@ -8,17 +8,23 @@ struct commit_list; struct contains_cache; struct ref_filter; -struct commit_list *get_merge_bases_many(struct commit *one, - int n, - struct commit **twos); -struct commit_list *get_merge_bases_many_dirty(struct commit *one, - int n, - struct commit **twos); -struct commit_list *get_merge_bases(struct commit *one, struct commit *two); -struct commit_list *get_octopus_merge_bases(struct commit_list *in); - +struct commit_list *repo_get_merge_bases(struct repository *r, + struct commit *rev1, + struct commit *rev2); +struct commit_list *repo_get_merge_bases_many(struct repository *r, + struct commit *one, int n, + struct commit **twos); /* To be used only when object flags after this call no longer matter */ -struct commit_list *get_merge_bases_many_dirty(struct commit *one, int n, struct commit **twos); +struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r, + struct commit *one, int n, + struct commit **twos); +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS +#define get_merge_bases(r1, r2) repo_get_merge_bases(the_repository, r1, r2) +#define get_merge_bases_many(one, n, two) repo_get_merge_bases_many(the_repository, one, n, two) +#define get_merge_bases_many_dirty(one, n, twos) repo_get_merge_bases_many_dirty(the_repository, one, n, twos) +#endif + +struct commit_list *get_octopus_merge_bases(struct commit_list *in); int is_descendant_of(struct commit *commit, struct commit_list *with_commit); int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit **reference); diff --git a/contrib/coccinelle/the_repository.pending.cocci b/contrib/coccinelle/the_repository.pending.cocci index b185fe0..f6c2915 100644 --- a/contrib/coccinelle/the_repository.pending.cocci +++ b/contrib/coccinelle/the_repository.pending.cocci @@ -64,3 +64,29 @@ expression E; - parse_commit( + repo_parse_commit(the_repository, E) + +@@ +expression E; +expression F; +@@ +- get_merge_bases( ++ repo_get_merge_bases(the_repository, + E, F); + +@@ +expression E; +expression F; +expression G; +@@ +- get_merge_bases_many( ++ repo_get_merge_bases_many(the_repository, + E, F, G); + +@@ +expression E; +expression F; +expression G; +@@ +- get_merge_bases_many_dirty( ++ repo_get_merge_bases_many_dirty(the_repository, + E, F, G); -- cgit v0.10.2-6-g49f6 From 4d5430f7479d45c3fca088984a08ec093f870b5b Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:56 -0800 Subject: commit-reach: prepare in_merge_bases[_many] to handle any repo Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/commit-reach.c b/commit-reach.c index 657a4e9..8715008 100644 --- a/commit-reach.c +++ b/commit-reach.c @@ -312,16 +312,17 @@ int is_descendant_of(struct commit *commit, struct commit_list *with_commit) /* * Is "commit" an ancestor of one of the "references"? */ -int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit **reference) +int repo_in_merge_bases_many(struct repository *r, struct commit *commit, + int nr_reference, struct commit **reference) { struct commit_list *bases; int ret = 0, i; uint32_t min_generation = GENERATION_NUMBER_INFINITY; - if (parse_commit(commit)) + if (repo_parse_commit(r, commit)) return ret; for (i = 0; i < nr_reference; i++) { - if (parse_commit(reference[i])) + if (repo_parse_commit(r, reference[i])) return ret; if (reference[i]->generation < min_generation) min_generation = reference[i]->generation; @@ -330,7 +331,7 @@ int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit * if (commit->generation > min_generation) return ret; - bases = paint_down_to_common(the_repository, commit, + bases = paint_down_to_common(r, commit, nr_reference, reference, commit->generation); if (commit->object.flags & PARENT2) @@ -344,9 +345,11 @@ int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit * /* * Is "commit" an ancestor of (i.e. reachable from) the "reference"? */ -int in_merge_bases(struct commit *commit, struct commit *reference) +int repo_in_merge_bases(struct repository *r, + struct commit *commit, + struct commit *reference) { - return in_merge_bases_many(commit, 1, &reference); + return repo_in_merge_bases_many(r, commit, 1, &reference); } struct commit_list *reduce_heads(struct commit_list *heads) diff --git a/commit-reach.h b/commit-reach.h index 52667d6..a0d4a29 100644 --- a/commit-reach.h +++ b/commit-reach.h @@ -27,8 +27,16 @@ struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r, struct commit_list *get_octopus_merge_bases(struct commit_list *in); int is_descendant_of(struct commit *commit, struct commit_list *with_commit); -int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit **reference); -int in_merge_bases(struct commit *commit, struct commit *reference); +int repo_in_merge_bases(struct repository *r, + struct commit *commit, + struct commit *reference); +int repo_in_merge_bases_many(struct repository *r, + struct commit *commit, + int nr_reference, struct commit **reference); +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS +#define in_merge_bases(c1, c2) repo_in_merge_bases(the_repository, c1, c2) +#define in_merge_bases_many(c1, n, cs) repo_in_merge_bases_many(the_repository, c1, n, cs) +#endif /* * Takes a list of commits and returns a new list where those diff --git a/contrib/coccinelle/the_repository.pending.cocci b/contrib/coccinelle/the_repository.pending.cocci index f6c2915..8c6a71b 100644 --- a/contrib/coccinelle/the_repository.pending.cocci +++ b/contrib/coccinelle/the_repository.pending.cocci @@ -90,3 +90,20 @@ expression G; - get_merge_bases_many_dirty( + repo_get_merge_bases_many_dirty(the_repository, E, F, G); + +@@ +expression E; +expression F; +@@ +- in_merge_bases( ++ repo_in_merge_bases(the_repository, + E, F); + +@@ +expression E; +expression F; +expression G; +@@ +- in_merge_bases_many( ++ repo_in_merge_bases_many(the_repository, + E, F, G); -- cgit v0.10.2-6-g49f6 From 07de3fd84049c90d8d873599c43c3979f37166aa Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:57 -0800 Subject: commit: prepare get_commit_buffer to handle any repo Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/commit.c b/commit.c index 7a931d7..4034def 100644 --- a/commit.c +++ b/commit.c @@ -297,13 +297,15 @@ const void *get_cached_commit_buffer(struct repository *r, const struct commit * return v->buffer; } -const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep) +const void *repo_get_commit_buffer(struct repository *r, + const struct commit *commit, + unsigned long *sizep) { - const void *ret = get_cached_commit_buffer(the_repository, commit, sizep); + const void *ret = get_cached_commit_buffer(r, commit, sizep); if (!ret) { enum object_type type; unsigned long size; - ret = read_object_file(&commit->object.oid, &type, &size); + ret = repo_read_object_file(r, &commit->object.oid, &type, &size); if (!ret) die("cannot read commit object %s", oid_to_hex(&commit->object.oid)); diff --git a/commit.h b/commit.h index 08935f9..591a77a 100644 --- a/commit.h +++ b/commit.h @@ -117,7 +117,12 @@ const void *get_cached_commit_buffer(struct repository *, const struct commit *, * 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); +const void *repo_get_commit_buffer(struct repository *r, + const struct commit *, + unsigned long *size); +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS +#define get_commit_buffer(c, s) repo_get_commit_buffer(the_repository, c, s) +#endif /* * Tell the commit subsytem that we are done with a particular commit buffer. diff --git a/contrib/coccinelle/the_repository.pending.cocci b/contrib/coccinelle/the_repository.pending.cocci index 8c6a71b..4018e6e 100644 --- a/contrib/coccinelle/the_repository.pending.cocci +++ b/contrib/coccinelle/the_repository.pending.cocci @@ -107,3 +107,11 @@ expression G; - in_merge_bases_many( + repo_in_merge_bases_many(the_repository, E, F, G); + +@@ +expression E; +expression F; +@@ +- get_commit_buffer( ++ repo_get_commit_buffer(the_repository, + E, F); -- cgit v0.10.2-6-g49f6 From 70315373ae51b45b9ca0ac43df396bb9035fe449 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:58 -0800 Subject: commit: prepare repo_unuse_commit_buffer to handle any repo Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/commit.c b/commit.c index 4034def..7d2f3a9 100644 --- a/commit.c +++ b/commit.c @@ -318,10 +318,12 @@ const void *repo_get_commit_buffer(struct repository *r, return ret; } -void unuse_commit_buffer(const struct commit *commit, const void *buffer) +void repo_unuse_commit_buffer(struct repository *r, + const struct commit *commit, + const void *buffer) { struct commit_buffer *v = buffer_slab_peek( - the_repository->parsed_objects->buffer_slab, commit); + r->parsed_objects->buffer_slab, commit); if (!(v && v->buffer == buffer)) free((void *)buffer); } diff --git a/commit.h b/commit.h index 591a77a..57375e3 100644 --- a/commit.h +++ b/commit.h @@ -130,7 +130,12 @@ const void *repo_get_commit_buffer(struct repository *r, * 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); +void repo_unuse_commit_buffer(struct repository *r, + const struct commit *, + const void *buffer); +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS +#define unuse_commit_buffer(c, b) repo_unuse_commit_buffer(the_repository, c, b) +#endif /* * Free any cached object buffer associated with the commit. diff --git a/contrib/coccinelle/the_repository.pending.cocci b/contrib/coccinelle/the_repository.pending.cocci index 4018e6e..516f19f 100644 --- a/contrib/coccinelle/the_repository.pending.cocci +++ b/contrib/coccinelle/the_repository.pending.cocci @@ -115,3 +115,11 @@ expression F; - get_commit_buffer( + repo_get_commit_buffer(the_repository, E, F); + +@@ +expression E; +expression F; +@@ +- unuse_commit_buffer( ++ repo_unuse_commit_buffer(the_repository, + E, F); -- cgit v0.10.2-6-g49f6 From 424510ed193fdc49cacc832d8795677d0cc54461 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:12:59 -0800 Subject: commit: prepare logmsg_reencode to handle arbitrary repositories Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/commit.h b/commit.h index 57375e3..2e6b799 100644 --- a/commit.h +++ b/commit.h @@ -180,6 +180,14 @@ extern int has_non_ascii(const char *text); extern const char *logmsg_reencode(const struct commit *commit, char **commit_encoding, const char *output_encoding); +const char *repo_logmsg_reencode(struct repository *r, + const struct commit *commit, + char **commit_encoding, + const char *output_encoding); +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS +#define logmsg_reencode(c, enc, out) repo_logmsg_reencode(the_repository, c, enc, out) +#endif + extern const char *skip_blank_lines(const char *msg); /** Removes the first commit from a list sorted by date, and adds all diff --git a/contrib/coccinelle/the_repository.pending.cocci b/contrib/coccinelle/the_repository.pending.cocci index 516f19f..f5b42cf 100644 --- a/contrib/coccinelle/the_repository.pending.cocci +++ b/contrib/coccinelle/the_repository.pending.cocci @@ -123,3 +123,12 @@ expression F; - unuse_commit_buffer( + repo_unuse_commit_buffer(the_repository, E, F); + +@@ +expression E; +expression F; +expression G; +@@ +- logmsg_reencode( ++ repo_logmsg_reencode(the_repository, + E, F, G); diff --git a/pretty.c b/pretty.c index 8ca29e9..b359b68 100644 --- a/pretty.c +++ b/pretty.c @@ -595,14 +595,15 @@ static char *replace_encoding_header(char *buf, const char *encoding) return strbuf_detach(&tmp, NULL); } -const char *logmsg_reencode(const struct commit *commit, - char **commit_encoding, - const char *output_encoding) +const char *repo_logmsg_reencode(struct repository *r, + const struct commit *commit, + char **commit_encoding, + const char *output_encoding) { static const char *utf8 = "UTF-8"; const char *use_encoding; char *encoding; - const char *msg = get_commit_buffer(commit, NULL); + const char *msg = repo_get_commit_buffer(r, commit, NULL); char *out; if (!output_encoding || !*output_encoding) { @@ -630,7 +631,7 @@ const char *logmsg_reencode(const struct commit *commit, * the cached copy from get_commit_buffer, we need to duplicate it * to avoid munging the cached copy. */ - if (msg == get_cached_commit_buffer(the_repository, commit, NULL)) + if (msg == get_cached_commit_buffer(r, commit, NULL)) out = xstrdup(msg); else out = (char *)msg; @@ -644,7 +645,7 @@ const char *logmsg_reencode(const struct commit *commit, */ out = reencode_string(msg, output_encoding, use_encoding); if (out) - unuse_commit_buffer(commit, msg); + repo_unuse_commit_buffer(r, commit, msg); } /* -- cgit v0.10.2-6-g49f6 From f54fbf5eefb9740a318344fe400f54f047cc4bf1 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Tue, 13 Nov 2018 16:13:00 -0800 Subject: pretty: prepare format_commit_message to handle arbitrary repositories Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/contrib/coccinelle/the_repository.pending.cocci b/contrib/coccinelle/the_repository.pending.cocci index f5b42cf..2ee702e 100644 --- a/contrib/coccinelle/the_repository.pending.cocci +++ b/contrib/coccinelle/the_repository.pending.cocci @@ -132,3 +132,13 @@ expression G; - logmsg_reencode( + repo_logmsg_reencode(the_repository, E, F, G); + +@@ +expression E; +expression F; +expression G; +expression H; +@@ +- format_commit_message( ++ repo_format_commit_message(the_repository, + E, F, G, H); diff --git a/pretty.c b/pretty.c index b359b68..3240495 100644 --- a/pretty.c +++ b/pretty.c @@ -1508,9 +1508,10 @@ void userformat_find_requirements(const char *fmt, struct userformat_want *w) strbuf_release(&dummy); } -void format_commit_message(const struct commit *commit, - const char *format, struct strbuf *sb, - const struct pretty_print_context *pretty_ctx) +void repo_format_commit_message(struct repository *r, + const struct commit *commit, + const char *format, struct strbuf *sb, + const struct pretty_print_context *pretty_ctx) { struct format_commit_context context; const char *output_enc = pretty_ctx->output_encoding; @@ -1524,9 +1525,9 @@ void format_commit_message(const struct commit *commit, * convert a commit message to UTF-8 first * as far as 'format_commit_item' assumes it in UTF-8 */ - context.message = logmsg_reencode(commit, - &context.commit_encoding, - utf8); + context.message = repo_logmsg_reencode(r, commit, + &context.commit_encoding, + utf8); strbuf_expand(sb, format, format_commit_item, &context); rewrap_message_tail(sb, &context, 0, 0, 0); @@ -1550,7 +1551,7 @@ void format_commit_message(const struct commit *commit, } free(context.commit_encoding); - unuse_commit_buffer(commit, context.message); + repo_unuse_commit_buffer(r, commit, context.message); } static void pp_header(struct pretty_print_context *pp, diff --git a/pretty.h b/pretty.h index 7359d31..e662526 100644 --- a/pretty.h +++ b/pretty.h @@ -103,9 +103,14 @@ void pp_remainder(struct pretty_print_context *pp, const char **msg_p, * Put the result to "sb". * Please use this function for custom formats. */ -void format_commit_message(const struct commit *commit, +void repo_format_commit_message(struct repository *r, + const struct commit *commit, const char *format, struct strbuf *sb, const struct pretty_print_context *context); +#ifndef NO_THE_REPOSITORY_COMPATIBILITY_MACROS +#define format_commit_message(c, f, s, con) \ + repo_format_commit_message(the_repository, c, f, s, con) +#endif /* * Parse given arguments from "arg", check it for correctness and -- cgit v0.10.2-6-g49f6 From 605f0ec1350477e53fd1a7774bad977257bf10d5 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Fri, 14 Dec 2018 16:09:37 -0800 Subject: submodule: use submodule repos for object lookup This converts the 'show_submodule_header' function to use the repository API properly, such that the submodule objects are not added to the main object store. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/submodule.c b/submodule.c index d9d3046..4486ff6 100644 --- a/submodule.c +++ b/submodule.c @@ -443,7 +443,7 @@ static int prepare_submodule_summary(struct rev_info *rev, const char *path, return prepare_revision_walk(rev); } -static void print_submodule_summary(struct rev_info *rev, struct diff_options *o) +static void print_submodule_summary(struct repository *r, struct rev_info *rev, struct diff_options *o) { static const char format[] = " %m %s"; struct strbuf sb = STRBUF_INIT; @@ -454,7 +454,8 @@ static void print_submodule_summary(struct rev_info *rev, struct diff_options *o ctx.date_mode = rev->date_mode; ctx.output_encoding = get_log_output_encoding(); strbuf_setlen(&sb, 0); - format_commit_message(commit, format, &sb, &ctx); + repo_format_commit_message(r, commit, format, &sb, + &ctx); strbuf_addch(&sb, '\n'); if (commit->object.flags & SYMMETRIC_LEFT) diff_emit_submodule_del(o, sb.buf); @@ -481,14 +482,46 @@ void prepare_submodule_repo_env(struct argv_array *out) DEFAULT_GIT_DIR_ENVIRONMENT); } -/* Helper function to display the submodule header line prior to the full - * summary output. If it can locate the submodule objects directory it will - * attempt to lookup both the left and right commits and put them into the - * left and right pointers. +/* + * Initialize a repository struct for a submodule based on the provided 'path'. + * + * Unlike repo_submodule_init, this tolerates submodules not present + * in .gitmodules. This function exists only to preserve historical behavior, + * + * Returns the repository struct on success, + * NULL when the submodule is not present. */ -static void show_submodule_header(struct diff_options *o, const char *path, +static struct repository *open_submodule(const char *path) +{ + struct strbuf sb = STRBUF_INIT; + struct repository *out = xmalloc(sizeof(*out)); + + if (submodule_to_gitdir(&sb, path) || repo_init(out, sb.buf, NULL)) { + strbuf_release(&sb); + free(out); + return NULL; + } + + /* Mark it as a submodule */ + out->submodule_prefix = xstrdup(path); + + strbuf_release(&sb); + return out; +} + +/* + * Helper function to display the submodule header line prior to the full + * summary output. + * + * If it can locate the submodule git directory it will create a repository + * handle for the submodule and lookup both the left and right commits and + * put them into the left and right pointers. + */ +static void show_submodule_header(struct diff_options *o, + const char *path, struct object_id *one, struct object_id *two, unsigned dirty_submodule, + struct repository *sub, struct commit **left, struct commit **right, struct commit_list **merge_bases) { @@ -507,7 +540,7 @@ static void show_submodule_header(struct diff_options *o, const char *path, else if (is_null_oid(two)) message = "(submodule deleted)"; - if (add_submodule_odb(path)) { + if (!sub) { if (!message) message = "(commits not present)"; goto output_header; @@ -517,8 +550,8 @@ static void show_submodule_header(struct diff_options *o, const char *path, * Attempt to lookup the commit references, and determine if this is * a fast forward or fast backwards update. */ - *left = lookup_commit_reference(the_repository, one); - *right = lookup_commit_reference(the_repository, two); + *left = lookup_commit_reference(sub, one); + *right = lookup_commit_reference(sub, two); /* * Warn about missing commits in the submodule project, but only if @@ -528,7 +561,7 @@ static void show_submodule_header(struct diff_options *o, const char *path, (!is_null_oid(two) && !*right)) message = "(commits not present)"; - *merge_bases = get_merge_bases(*left, *right); + *merge_bases = repo_get_merge_bases(sub, *left, *right); if (*merge_bases) { if ((*merge_bases)->item == *left) fast_forward = 1; @@ -562,16 +595,18 @@ void show_submodule_summary(struct diff_options *o, const char *path, struct rev_info rev; struct commit *left = NULL, *right = NULL; struct commit_list *merge_bases = NULL; + struct repository *sub; + sub = open_submodule(path); show_submodule_header(o, path, one, two, dirty_submodule, - &left, &right, &merge_bases); + sub, &left, &right, &merge_bases); /* * If we don't have both a left and a right pointer, there is no * reason to try and display a summary. The header line should contain * all the information the user needs. */ - if (!left || !right) + if (!left || !right || !sub) goto out; /* Treat revision walker failure the same as missing commits */ @@ -580,13 +615,17 @@ void show_submodule_summary(struct diff_options *o, const char *path, goto out; } - print_submodule_summary(&rev, o); + print_submodule_summary(sub, &rev, o); out: if (merge_bases) free_commit_list(merge_bases); clear_commit_marks(left, ~0); clear_commit_marks(right, ~0); + if (sub) { + repo_clear(sub); + free(sub); + } } void show_submodule_inline_diff(struct diff_options *o, const char *path, @@ -598,9 +637,11 @@ void show_submodule_inline_diff(struct diff_options *o, const char *path, struct commit_list *merge_bases = NULL; struct child_process cp = CHILD_PROCESS_INIT; struct strbuf sb = STRBUF_INIT; + struct repository *sub; + sub = open_submodule(path); show_submodule_header(o, path, one, two, dirty_submodule, - &left, &right, &merge_bases); + sub, &left, &right, &merge_bases); /* We need a valid left and right commit to display a difference */ if (!(left || is_null_oid(one)) || @@ -661,6 +702,10 @@ done: clear_commit_marks(left, ~0); if (right) clear_commit_marks(right, ~0); + if (sub) { + repo_clear(sub); + free(sub); + } } int should_update_submodules(void) -- cgit v0.10.2-6-g49f6 From 142e9f4432199cec5de418d74b37872d8330f696 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Fri, 14 Dec 2018 16:09:38 -0800 Subject: submodule: don't add submodule as odb for push In push_submodule(), because we do not actually need access to objects in the submodule, do not invoke add_submodule_odb(). (for_each_remote_ref_submodule() does not require access to those objects, and the actual push is done by spawning another process, which handles object access by itself.) This code of push_submodule() is exercised in t5531 and continues to work, showing that the submodule odbc is not needed. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/submodule.c b/submodule.c index 4486ff6..d9c0676 100644 --- a/submodule.c +++ b/submodule.c @@ -1023,9 +1023,6 @@ static int push_submodule(const char *path, const struct string_list *push_options, int dry_run) { - if (add_submodule_odb(path)) - return 1; - if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) { struct child_process cp = CHILD_PROCESS_INIT; argv_array_push(&cp.args, "push"); -- cgit v0.10.2-6-g49f6 From 4f542b7a7f944986e3f7567f7e94b256b1929f6c Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Fri, 14 Dec 2018 16:09:39 -0800 Subject: commit-graph: convert remaining functions to handle any repo Convert all functions to handle arbitrary repositories in commit-graph.c that are used by functions taking a repository argument already. Notable exclusion is write_commit_graph and its local functions as that only works on the_repository. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/commit-graph.c b/commit-graph.c index 40c855f..f78a8e9 100644 --- a/commit-graph.c +++ b/commit-graph.c @@ -292,7 +292,8 @@ static int bsearch_graph(struct commit_graph *g, struct object_id *oid, uint32_t g->chunk_oid_lookup, g->hash_len, pos); } -static struct commit_list **insert_parent_or_die(struct commit_graph *g, +static struct commit_list **insert_parent_or_die(struct repository *r, + struct commit_graph *g, uint64_t pos, struct commit_list **pptr) { @@ -303,7 +304,7 @@ static struct commit_list **insert_parent_or_die(struct commit_graph *g, die("invalid parent position %"PRIu64, pos); hashcpy(oid.hash, g->chunk_oid_lookup + g->hash_len * pos); - c = lookup_commit(the_repository, &oid); + c = lookup_commit(r, &oid); if (!c) die(_("could not find commit %s"), oid_to_hex(&oid)); c->graph_pos = pos; @@ -317,7 +318,9 @@ static void fill_commit_graph_info(struct commit *item, struct commit_graph *g, item->generation = get_be32(commit_data + g->hash_len + 8) >> 2; } -static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uint32_t pos) +static int fill_commit_in_graph(struct repository *r, + struct commit *item, + struct commit_graph *g, uint32_t pos) { uint32_t edge_value; uint32_t *parent_data_ptr; @@ -341,13 +344,13 @@ static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uin edge_value = get_be32(commit_data + g->hash_len); if (edge_value == GRAPH_PARENT_NONE) return 1; - pptr = insert_parent_or_die(g, edge_value, pptr); + pptr = insert_parent_or_die(r, g, edge_value, pptr); edge_value = get_be32(commit_data + g->hash_len + 4); if (edge_value == GRAPH_PARENT_NONE) return 1; if (!(edge_value & GRAPH_OCTOPUS_EDGES_NEEDED)) { - pptr = insert_parent_or_die(g, edge_value, pptr); + pptr = insert_parent_or_die(r, g, edge_value, pptr); return 1; } @@ -355,7 +358,7 @@ static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uin 4 * (uint64_t)(edge_value & GRAPH_EDGE_LAST_MASK)); do { edge_value = get_be32(parent_data_ptr); - pptr = insert_parent_or_die(g, + pptr = insert_parent_or_die(r, g, edge_value & GRAPH_EDGE_LAST_MASK, pptr); parent_data_ptr++; @@ -374,7 +377,9 @@ static int find_commit_in_graph(struct commit *item, struct commit_graph *g, uin } } -static int parse_commit_in_graph_one(struct commit_graph *g, struct commit *item) +static int parse_commit_in_graph_one(struct repository *r, + struct commit_graph *g, + struct commit *item) { uint32_t pos; @@ -382,7 +387,7 @@ static int parse_commit_in_graph_one(struct commit_graph *g, struct commit *item return 1; if (find_commit_in_graph(item, g, &pos)) - return fill_commit_in_graph(item, g, pos); + return fill_commit_in_graph(r, item, g, pos); return 0; } @@ -391,7 +396,7 @@ int parse_commit_in_graph(struct repository *r, struct commit *item) { if (!prepare_commit_graph(r)) return 0; - return parse_commit_in_graph_one(r->objects->commit_graph, item); + return parse_commit_in_graph_one(r, r->objects->commit_graph, item); } void load_commit_graph_info(struct repository *r, struct commit *item) @@ -403,19 +408,22 @@ void load_commit_graph_info(struct repository *r, struct commit *item) fill_commit_graph_info(item, r->objects->commit_graph, pos); } -static struct tree *load_tree_for_commit(struct commit_graph *g, struct commit *c) +static struct tree *load_tree_for_commit(struct repository *r, + struct commit_graph *g, + struct commit *c) { struct object_id oid; const unsigned char *commit_data = g->chunk_commit_data + GRAPH_DATA_WIDTH * (c->graph_pos); hashcpy(oid.hash, commit_data); - c->maybe_tree = lookup_tree(the_repository, &oid); + c->maybe_tree = lookup_tree(r, &oid); return c->maybe_tree; } -static struct tree *get_commit_tree_in_graph_one(struct commit_graph *g, +static struct tree *get_commit_tree_in_graph_one(struct repository *r, + struct commit_graph *g, const struct commit *c) { if (c->maybe_tree) @@ -423,12 +431,12 @@ static struct tree *get_commit_tree_in_graph_one(struct commit_graph *g, if (c->graph_pos == COMMIT_NOT_FROM_GRAPH) BUG("get_commit_tree_in_graph_one called from non-commit-graph commit"); - return load_tree_for_commit(g, (struct commit *)c); + return load_tree_for_commit(r, g, (struct commit *)c); } struct tree *get_commit_tree_in_graph(struct repository *r, const struct commit *c) { - return get_commit_tree_in_graph_one(r->objects->commit_graph, c); + return get_commit_tree_in_graph_one(r, r->objects->commit_graph, c); } static void write_graph_chunk_fanout(struct hashfile *f, @@ -1025,7 +1033,7 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g) } graph_commit = lookup_commit(r, &cur_oid); - if (!parse_commit_in_graph_one(g, graph_commit)) + if (!parse_commit_in_graph_one(r, g, graph_commit)) graph_report("failed to parse %s from commit-graph", oid_to_hex(&cur_oid)); } @@ -1061,7 +1069,7 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g) continue; } - if (!oideq(&get_commit_tree_in_graph_one(g, graph_commit)->object.oid, + if (!oideq(&get_commit_tree_in_graph_one(r, g, graph_commit)->object.oid, get_commit_tree_oid(odb_commit))) graph_report("root tree OID for commit %s in commit-graph is %s != %s", oid_to_hex(&cur_oid), -- cgit v0.10.2-6-g49f6 From 6a7895fd8a3bd409f2b71ffc355d5142172cc2a0 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Fri, 14 Dec 2018 16:09:40 -0800 Subject: commit: prepare free_commit_buffer and release_commit_memory for any repo Pass the object pool to free_commit_buffer and release_commit_memory, such that we can eliminate access to 'the_repository'. Also remove the TODO in release_commit_memory, as commit->util was removed in 9d2c97016f (commit.h: delete 'util' field in struct commit, 2018-05-19) Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/builtin/fsck.c b/builtin/fsck.c index 06eb421..c476ac6 100644 --- a/builtin/fsck.c +++ b/builtin/fsck.c @@ -382,7 +382,8 @@ out: if (obj->type == OBJ_TREE) free_tree_buffer((struct tree *)obj); if (obj->type == OBJ_COMMIT) - free_commit_buffer((struct commit *)obj); + free_commit_buffer(the_repository->parsed_objects, + (struct commit *)obj); return err; } diff --git a/builtin/log.c b/builtin/log.c index 061d4fd..64c2649 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -395,7 +395,8 @@ static int cmd_log_walk(struct rev_info *rev) * We may show a given commit multiple times when * walking the reflogs. */ - free_commit_buffer(commit); + free_commit_buffer(the_repository->parsed_objects, + commit); free_commit_list(commit->parents); commit->parents = NULL; } @@ -1922,7 +1923,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix) open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet)) die(_("Failed to create output files")); shown = log_tree_commit(&rev, commit); - free_commit_buffer(commit); + free_commit_buffer(the_repository->parsed_objects, + 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 cc1b705..2b301fa 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -196,7 +196,8 @@ static void finish_commit(struct commit *commit, void *data) free_commit_list(commit->parents); commit->parents = NULL; } - free_commit_buffer(commit); + free_commit_buffer(the_repository->parsed_objects, + commit); } static inline void finish_object__ma(struct object *obj) diff --git a/commit.c b/commit.c index 7d2f3a9..4fe74aa 100644 --- a/commit.c +++ b/commit.c @@ -328,10 +328,10 @@ void repo_unuse_commit_buffer(struct repository *r, free((void *)buffer); } -void free_commit_buffer(struct commit *commit) +void free_commit_buffer(struct parsed_object_pool *pool, struct commit *commit) { struct commit_buffer *v = buffer_slab_peek( - the_repository->parsed_objects->buffer_slab, commit); + pool->buffer_slab, commit); if (v) { FREE_AND_NULL(v->buffer); v->size = 0; @@ -354,13 +354,12 @@ struct object_id *get_commit_tree_oid(const struct commit *commit) return &get_commit_tree(commit)->object.oid; } -void release_commit_memory(struct commit *c) +void release_commit_memory(struct parsed_object_pool *pool, struct commit *c) { c->maybe_tree = NULL; c->index = 0; - free_commit_buffer(c); + free_commit_buffer(pool, c); free_commit_list(c->parents); - /* TODO: what about commit->util? */ c->object.parsed = 0; } diff --git a/commit.h b/commit.h index 2e6b799..d2779a2 100644 --- a/commit.h +++ b/commit.h @@ -140,7 +140,7 @@ void repo_unuse_commit_buffer(struct repository *r, /* * Free any cached object buffer associated with the commit. */ -void free_commit_buffer(struct commit *); +void free_commit_buffer(struct parsed_object_pool *pool, struct commit *); struct tree *get_commit_tree(const struct commit *); struct object_id *get_commit_tree_oid(const struct commit *); @@ -149,7 +149,7 @@ struct object_id *get_commit_tree_oid(const struct commit *); * Release memory related to a commit, including the parent list and * any cached object buffer. */ -void release_commit_memory(struct commit *c); +void release_commit_memory(struct parsed_object_pool *pool, struct commit *c); /* * Disassociate any cached object buffer from the commit, but do not free it. diff --git a/object.c b/object.c index 003f870..c4170d2 100644 --- a/object.c +++ b/object.c @@ -540,7 +540,7 @@ void parsed_object_pool_clear(struct parsed_object_pool *o) if (obj->type == OBJ_TREE) free_tree_buffer((struct tree*)obj); else if (obj->type == OBJ_COMMIT) - release_commit_memory((struct commit*)obj); + release_commit_memory(o, (struct commit*)obj); else if (obj->type == OBJ_TAG) release_tag_memory((struct tag*)obj); } -- cgit v0.10.2-6-g49f6 From b6b24fc57bb2132955756771f9588a3cfb050350 Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Fri, 14 Dec 2018 16:09:41 -0800 Subject: path.h: make REPO_GIT_PATH_FUNC repository agnostic git_pathdup uses the_repository internally, but the macro REPO_GIT_PATH_FUNC is specifically made for arbitrary repositories. Switch to repo_git_path which works on arbitrary repositories. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/path.h b/path.h index b654ea8..651e615 100644 --- a/path.h +++ b/path.h @@ -165,7 +165,7 @@ extern void report_linked_checkout_garbage(void); const char *git_path_##var(struct repository *r) \ { \ if (!r->cached_paths.var) \ - r->cached_paths.var = git_pathdup(filename); \ + r->cached_paths.var = repo_git_path(r, filename); \ return r->cached_paths.var; \ } -- cgit v0.10.2-6-g49f6 From ff509c585e847c5fc40c40d35e7d745dd81363bd Mon Sep 17 00:00:00 2001 From: Stefan Beller Date: Fri, 14 Dec 2018 16:09:42 -0800 Subject: t/helper/test-repository: celebrate independence from the_repository dade47c06c (commit-graph: add repo arg to graph readers, 2018-07-11) brought more independence from the_repository to the commit graph, however it was not completely independent of the_repository, as the previous patches show. To ensure we're not accessing the_repository by accident, we'd ideally assign NULL to the_repository to trigger a segfault on access. We currently have a temporary hack in cache.h, which relies on the_hash_algo (which is a short form of the_repository->hash_algo) to be set, so we cannot do that. The next best thing is to set all fields of the_repository to 0, so any accidental access is more likely to be found. Signed-off-by: Stefan Beller Signed-off-by: Junio C Hamano diff --git a/cache.h b/cache.h index 59c8a93..8864d7e 100644 --- a/cache.h +++ b/cache.h @@ -1033,6 +1033,8 @@ static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2) * * This will need to be extended or ripped out when we learn about * hashes of different sizes. + * + * When ripping this out, see TODO in test-repository.c. */ if (the_hash_algo->rawsz != 20) BUG("hash size not yet supported by hashcmp"); diff --git a/t/helper/test-repository.c b/t/helper/test-repository.c index 6a84a53..f7f8618 100644 --- a/t/helper/test-repository.c +++ b/t/helper/test-repository.c @@ -17,6 +17,11 @@ static void test_parse_commit_in_graph(const char *gitdir, const char *worktree, setup_git_env(gitdir); + memset(the_repository, 0, sizeof(*the_repository)); + + /* TODO: Needed for temporary hack in hashcmp, see 183a638b7da. */ + repo_set_hash_algo(the_repository, GIT_HASH_SHA1); + if (repo_init(&r, gitdir, worktree)) die("Couldn't init repo"); @@ -43,6 +48,11 @@ static void test_get_commit_tree_in_graph(const char *gitdir, setup_git_env(gitdir); + memset(the_repository, 0, sizeof(*the_repository)); + + /* TODO: Needed for temporary hack in hashcmp, see 183a638b7da. */ + repo_set_hash_algo(the_repository, GIT_HASH_SHA1); + if (repo_init(&r, gitdir, worktree)) die("Couldn't init repo"); -- cgit v0.10.2-6-g49f6