Merge branch 'sb/more-repo-in-api'

The in-core repository instances are passed through more codepaths.

* sb/more-repo-in-api: (23 commits)
  t/helper/test-repository: celebrate independence from the_repository
  path.h: make REPO_GIT_PATH_FUNC repository agnostic
  commit: prepare free_commit_buffer and release_commit_memory for any repo
  commit-graph: convert remaining functions to handle any repo
  submodule: don't add submodule as odb for push
  submodule: use submodule repos for object lookup
  pretty: prepare format_commit_message to handle arbitrary repositories
  commit: prepare logmsg_reencode to handle arbitrary repositories
  commit: prepare repo_unuse_commit_buffer to handle any repo
  commit: prepare get_commit_buffer to handle any repo
  commit-reach: prepare in_merge_bases[_many] to handle any repo
  commit-reach: prepare get_merge_bases to handle any repo
  commit-reach.c: allow get_merge_bases_many_0 to handle any repo
  commit-reach.c: allow remove_redundant to handle any repo
  commit-reach.c: allow merge_bases_many to handle any repo
  commit-reach.c: allow paint_down_to_common to handle any repo
  commit: allow parse_commit* to handle any repo
  object: parse_object to honor its repository argument
  object-store: prepare has_{sha1, object}_file to handle any repo
  object-store: prepare read_object_file to deal with any repo
  ...
This commit is contained in:
Junio C Hamano 2019-02-05 14:26:09 -08:00
commit b99a579f8e
20 changed files with 452 additions and 150 deletions

View File

@ -401,7 +401,8 @@ out:
if (obj->type == OBJ_TREE) if (obj->type == OBJ_TREE)
free_tree_buffer((struct tree *)obj); free_tree_buffer((struct tree *)obj);
if (obj->type == OBJ_COMMIT) if (obj->type == OBJ_COMMIT)
free_commit_buffer((struct commit *)obj); free_commit_buffer(the_repository->parsed_objects,
(struct commit *)obj);
return err; return err;
} }

View File

@ -397,7 +397,8 @@ static int cmd_log_walk(struct rev_info *rev)
* We may show a given commit multiple times when * We may show a given commit multiple times when
* walking the reflogs. * walking the reflogs.
*/ */
free_commit_buffer(commit); free_commit_buffer(the_repository->parsed_objects,
commit);
free_commit_list(commit->parents); free_commit_list(commit->parents);
commit->parents = NULL; commit->parents = NULL;
} }
@ -1940,7 +1941,8 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet)) open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
die(_("Failed to create output files")); die(_("Failed to create output files"));
shown = log_tree_commit(&rev, commit); 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 /* We put one extra blank line between formatted
* patches and this flag is used by log-tree code * patches and this flag is used by log-tree code

View File

@ -197,7 +197,8 @@ static void finish_commit(struct commit *commit, void *data)
free_commit_list(commit->parents); free_commit_list(commit->parents);
commit->parents = NULL; commit->parents = NULL;
} }
free_commit_buffer(commit); free_commit_buffer(the_repository->parsed_objects,
commit);
} }
static inline void finish_object__ma(struct object *obj) static inline void finish_object__ma(struct object *obj)

View File

@ -288,7 +288,8 @@ static int bsearch_graph(struct commit_graph *g, struct object_id *oid, uint32_t
g->chunk_oid_lookup, g->hash_len, pos); 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, uint64_t pos,
struct commit_list **pptr) struct commit_list **pptr)
{ {
@ -299,7 +300,7 @@ static struct commit_list **insert_parent_or_die(struct commit_graph *g,
die("invalid parent position %"PRIu64, pos); die("invalid parent position %"PRIu64, pos);
hashcpy(oid.hash, g->chunk_oid_lookup + g->hash_len * 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) if (!c)
die(_("could not find commit %s"), oid_to_hex(&oid)); die(_("could not find commit %s"), oid_to_hex(&oid));
c->graph_pos = pos; c->graph_pos = pos;
@ -313,7 +314,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; 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 edge_value;
uint32_t *parent_data_ptr; uint32_t *parent_data_ptr;
@ -337,13 +340,13 @@ static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uin
edge_value = get_be32(commit_data + g->hash_len); edge_value = get_be32(commit_data + g->hash_len);
if (edge_value == GRAPH_PARENT_NONE) if (edge_value == GRAPH_PARENT_NONE)
return 1; 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); edge_value = get_be32(commit_data + g->hash_len + 4);
if (edge_value == GRAPH_PARENT_NONE) if (edge_value == GRAPH_PARENT_NONE)
return 1; return 1;
if (!(edge_value & GRAPH_OCTOPUS_EDGES_NEEDED)) { 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; return 1;
} }
@ -351,7 +354,7 @@ static int fill_commit_in_graph(struct commit *item, struct commit_graph *g, uin
4 * (uint64_t)(edge_value & GRAPH_EDGE_LAST_MASK)); 4 * (uint64_t)(edge_value & GRAPH_EDGE_LAST_MASK));
do { do {
edge_value = get_be32(parent_data_ptr); 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, edge_value & GRAPH_EDGE_LAST_MASK,
pptr); pptr);
parent_data_ptr++; parent_data_ptr++;
@ -370,7 +373,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; uint32_t pos;
@ -378,7 +383,7 @@ static int parse_commit_in_graph_one(struct commit_graph *g, struct commit *item
return 1; return 1;
if (find_commit_in_graph(item, g, &pos)) 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; return 0;
} }
@ -387,7 +392,7 @@ int parse_commit_in_graph(struct repository *r, struct commit *item)
{ {
if (!prepare_commit_graph(r)) if (!prepare_commit_graph(r))
return 0; 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) void load_commit_graph_info(struct repository *r, struct commit *item)
@ -399,19 +404,22 @@ void load_commit_graph_info(struct repository *r, struct commit *item)
fill_commit_graph_info(item, r->objects->commit_graph, pos); 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; struct object_id oid;
const unsigned char *commit_data = g->chunk_commit_data + const unsigned char *commit_data = g->chunk_commit_data +
GRAPH_DATA_WIDTH * (c->graph_pos); GRAPH_DATA_WIDTH * (c->graph_pos);
hashcpy(oid.hash, commit_data); hashcpy(oid.hash, commit_data);
c->maybe_tree = lookup_tree(the_repository, &oid); c->maybe_tree = lookup_tree(r, &oid);
return c->maybe_tree; 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) const struct commit *c)
{ {
if (c->maybe_tree) if (c->maybe_tree)
@ -419,12 +427,12 @@ static struct tree *get_commit_tree_in_graph_one(struct commit_graph *g,
if (c->graph_pos == COMMIT_NOT_FROM_GRAPH) if (c->graph_pos == COMMIT_NOT_FROM_GRAPH)
BUG("get_commit_tree_in_graph_one called from non-commit-graph commit"); 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) 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, static void write_graph_chunk_fanout(struct hashfile *f,
@ -1035,7 +1043,7 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g)
} }
graph_commit = lookup_commit(r, &cur_oid); 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", graph_report("failed to parse %s from commit-graph",
oid_to_hex(&cur_oid)); oid_to_hex(&cur_oid));
} }
@ -1071,7 +1079,7 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g)
continue; 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))) get_commit_tree_oid(odb_commit)))
graph_report("root tree OID for commit %s in commit-graph is %s != %s", graph_report("root tree OID for commit %s in commit-graph is %s != %s",
oid_to_hex(&cur_oid), oid_to_hex(&cur_oid),

View File

@ -30,7 +30,8 @@ static int queue_has_nonstale(struct prio_queue *queue)
} }
/* all input commits in one and twos[] must have been parsed! */ /* 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, struct commit **twos,
int min_generation) int min_generation)
{ {
@ -83,7 +84,7 @@ static struct commit_list *paint_down_to_common(struct commit *one, int n,
parents = parents->next; parents = parents->next;
if ((p->object.flags & flags) == flags) if ((p->object.flags & flags) == flags)
continue; continue;
if (parse_commit(p)) if (repo_parse_commit(r, p))
return NULL; return NULL;
p->object.flags |= flags; p->object.flags |= flags;
prio_queue_put(&queue, p); prio_queue_put(&queue, p);
@ -94,7 +95,9 @@ static struct commit_list *paint_down_to_common(struct commit *one, int n,
return result; 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 *list = NULL;
struct commit_list *result = NULL; struct commit_list *result = NULL;
@ -109,14 +112,14 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co
return commit_list_insert(one, &result); return commit_list_insert(one, &result);
} }
if (parse_commit(one)) if (repo_parse_commit(r, one))
return NULL; return NULL;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (parse_commit(twos[i])) if (repo_parse_commit(r, twos[i]))
return NULL; return NULL;
} }
list = paint_down_to_common(one, n, twos, 0); list = paint_down_to_common(r, one, n, twos, 0);
while (list) { while (list) {
struct commit *commit = pop_commit(&list); struct commit *commit = pop_commit(&list);
@ -153,7 +156,7 @@ struct commit_list *get_octopus_merge_bases(struct commit_list *in)
return ret; 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 * Some commit in the array may be an ancestor of
@ -171,7 +174,7 @@ static int remove_redundant(struct commit **array, int cnt)
ALLOC_ARRAY(filled_index, cnt - 1); ALLOC_ARRAY(filled_index, cnt - 1);
for (i = 0; i < cnt; i++) for (i = 0; i < cnt; i++)
parse_commit(array[i]); repo_parse_commit(r, array[i]);
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
struct commit_list *common; struct commit_list *common;
uint32_t min_generation = array[i]->generation; uint32_t min_generation = array[i]->generation;
@ -187,8 +190,8 @@ static int remove_redundant(struct commit **array, int cnt)
if (array[j]->generation < min_generation) if (array[j]->generation < min_generation)
min_generation = array[j]->generation; min_generation = array[j]->generation;
} }
common = paint_down_to_common(array[i], filled, work, common = paint_down_to_common(r, array[i], filled,
min_generation); work, min_generation);
if (array[i]->object.flags & PARENT2) if (array[i]->object.flags & PARENT2)
redundant[i] = 1; redundant[i] = 1;
for (j = 0; j < filled; j++) for (j = 0; j < filled; j++)
@ -213,7 +216,8 @@ static int remove_redundant(struct commit **array, int cnt)
return filled; 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, int n,
struct commit **twos, struct commit **twos,
int cleanup) int cleanup)
@ -223,7 +227,7 @@ static struct commit_list *get_merge_bases_many_0(struct commit *one,
struct commit_list *result; struct commit_list *result;
int cnt, i; int cnt, i;
result = merge_bases_many(one, n, twos); result = merge_bases_many(r, one, n, twos);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (one == twos[i]) if (one == twos[i])
return result; return result;
@ -246,7 +250,7 @@ static struct commit_list *get_merge_bases_many_0(struct commit *one,
clear_commit_marks(one, all_flags); clear_commit_marks(one, all_flags);
clear_commit_marks_many(n, twos, all_flags); clear_commit_marks_many(n, twos, all_flags);
cnt = remove_redundant(rslt, cnt); cnt = remove_redundant(r, rslt, cnt);
result = NULL; result = NULL;
for (i = 0; i < cnt; i++) for (i = 0; i < cnt; i++)
commit_list_insert_by_date(rslt[i], &result); commit_list_insert_by_date(rslt[i], &result);
@ -254,23 +258,27 @@ static struct commit_list *get_merge_bases_many_0(struct commit *one,
return result; return result;
} }
struct commit_list *get_merge_bases_many(struct commit *one, struct commit_list *repo_get_merge_bases_many(struct repository *r,
int n, struct commit *one,
struct commit **twos) int n,
struct commit **twos)
{ {
return get_merge_bases_many_0(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, struct commit_list *repo_get_merge_bases_many_dirty(struct repository *r,
int n, struct commit *one,
struct commit **twos) int n,
struct commit **twos)
{ {
return get_merge_bases_many_0(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(one, 1, &two, 1); return get_merge_bases_many_0(r, one, 1, &two, 1);
} }
/* /*
@ -304,16 +312,17 @@ int is_descendant_of(struct commit *commit, struct commit_list *with_commit)
/* /*
* Is "commit" an ancestor of one of the "references"? * 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; struct commit_list *bases;
int ret = 0, i; int ret = 0, i;
uint32_t min_generation = GENERATION_NUMBER_INFINITY; uint32_t min_generation = GENERATION_NUMBER_INFINITY;
if (parse_commit(commit)) if (repo_parse_commit(r, commit))
return ret; return ret;
for (i = 0; i < nr_reference; i++) { for (i = 0; i < nr_reference; i++) {
if (parse_commit(reference[i])) if (repo_parse_commit(r, reference[i]))
return ret; return ret;
if (reference[i]->generation < min_generation) if (reference[i]->generation < min_generation)
min_generation = reference[i]->generation; min_generation = reference[i]->generation;
@ -322,7 +331,9 @@ int in_merge_bases_many(struct commit *commit, int nr_reference, struct commit *
if (commit->generation > min_generation) if (commit->generation > min_generation)
return ret; return ret;
bases = paint_down_to_common(commit, nr_reference, reference, commit->generation); bases = paint_down_to_common(r, commit,
nr_reference, reference,
commit->generation);
if (commit->object.flags & PARENT2) if (commit->object.flags & PARENT2)
ret = 1; ret = 1;
clear_commit_marks(commit, all_flags); clear_commit_marks(commit, all_flags);
@ -334,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"? * 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) struct commit_list *reduce_heads(struct commit_list *heads)
@ -365,7 +378,7 @@ struct commit_list *reduce_heads(struct commit_list *heads)
p->item->object.flags &= ~STALE; 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++) for (i = 0; i < num_head; i++)
tail = &commit_list_insert(array[i], tail)->next; tail = &commit_list_insert(array[i], tail)->next;
free(array); free(array);

View File

@ -9,21 +9,35 @@ struct ref_filter;
struct object_id; struct object_id;
struct object_array; struct object_array;
struct commit_list *get_merge_bases_many(struct commit *one, struct commit_list *repo_get_merge_bases(struct repository *r,
int n, struct commit *rev1,
struct commit **twos); struct commit *rev2);
struct commit_list *get_merge_bases_many_dirty(struct commit *one, struct commit_list *repo_get_merge_bases_many(struct repository *r,
int n, struct commit *one, int n,
struct commit **twos); struct commit **twos);
struct commit_list *get_merge_bases(struct commit *one, struct commit *two); /* To be used only when object flags after this call no longer matter */
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); struct commit_list *get_octopus_merge_bases(struct commit_list *in);
/* 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);
int is_descendant_of(struct commit *commit, struct commit_list *with_commit); 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 repo_in_merge_bases(struct repository *r,
int in_merge_bases(struct commit *commit, struct commit *reference); 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 * Takes a list of commits and returns a new list where those

View File

@ -299,13 +299,15 @@ const void *get_cached_commit_buffer(struct repository *r, const struct commit *
return v->buffer; 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) { if (!ret) {
enum object_type type; enum object_type type;
unsigned long size; 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) if (!ret)
die("cannot read commit object %s", die("cannot read commit object %s",
oid_to_hex(&commit->object.oid)); oid_to_hex(&commit->object.oid));
@ -318,18 +320,20 @@ const void *get_commit_buffer(const struct commit *commit, unsigned long *sizep)
return ret; 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( 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)) if (!(v && v->buffer == buffer))
free((void *)buffer); 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( struct commit_buffer *v = buffer_slab_peek(
the_repository->parsed_objects->buffer_slab, commit); pool->buffer_slab, commit);
if (v) { if (v) {
FREE_AND_NULL(v->buffer); FREE_AND_NULL(v->buffer);
v->size = 0; v->size = 0;
@ -352,13 +356,12 @@ struct object_id *get_commit_tree_oid(const struct commit *commit)
return &get_commit_tree(commit)->object.oid; 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->maybe_tree = NULL;
c->index = 0; c->index = 0;
free_commit_buffer(c); free_commit_buffer(pool, c);
free_commit_list(c->parents); free_commit_list(c->parents);
/* TODO: what about commit->util? */
c->object.parsed = 0; c->object.parsed = 0;
} }
@ -445,7 +448,10 @@ int parse_commit_buffer(struct repository *r, struct commit *item, const void *b
return 0; 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; enum object_type type;
void *buffer; void *buffer;
@ -456,9 +462,9 @@ int parse_commit_internal(struct commit *item, int quiet_on_missing, int use_com
return -1; return -1;
if (item->object.parsed) if (item->object.parsed)
return 0; 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; return 0;
buffer = read_object_file(&item->object.oid, &type, &size); buffer = repo_read_object_file(r, &item->object.oid, &type, &size);
if (!buffer) if (!buffer)
return quiet_on_missing ? -1 : return quiet_on_missing ? -1 :
error("Could not read %s", error("Could not read %s",
@ -469,18 +475,19 @@ int parse_commit_internal(struct commit *item, int quiet_on_missing, int use_com
oid_to_hex(&item->object.oid)); 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) { if (save_commit_buffer && !ret) {
set_commit_buffer(the_repository, item, buffer, size); set_commit_buffer(r, item, buffer, size);
return 0; return 0;
} }
free(buffer); free(buffer);
return ret; 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) void parse_commit_or_die(struct commit *item)

View File

@ -80,12 +80,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); 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_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 repo_parse_commit_internal(struct repository *r, struct commit *item,
int parse_commit_gently(struct commit *item, int quiet_on_missing); int quiet_on_missing, int use_commit_graph);
static inline int parse_commit(struct commit *item) 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); void parse_commit_or_die(struct commit *item);
struct buffer_slab; struct buffer_slab;
@ -109,7 +118,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 * from disk. The resulting memory should not be modified, and must be given
* to unuse_commit_buffer when the caller is done. * 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. * Tell the commit subsytem that we are done with a particular commit buffer.
@ -117,12 +131,17 @@ const void *get_commit_buffer(const struct commit *, unsigned long *size);
* from an earlier call to get_commit_buffer. The buffer may or may not be * 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. * 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. * 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 tree *get_commit_tree(const struct commit *);
struct object_id *get_commit_tree_oid(const struct commit *); struct object_id *get_commit_tree_oid(const struct commit *);
@ -131,7 +150,7 @@ struct object_id *get_commit_tree_oid(const struct commit *);
* Release memory related to a commit, including the parent list and * Release memory related to a commit, including the parent list and
* any cached object buffer. * 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. * Disassociate any cached object buffer from the commit, but do not free it.
@ -162,6 +181,14 @@ extern int has_non_ascii(const char *text);
extern const char *logmsg_reencode(const struct commit *commit, extern const char *logmsg_reencode(const struct commit *commit,
char **commit_encoding, char **commit_encoding,
const char *output_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); extern const char *skip_blank_lines(const char *msg);
/** Removes the first commit from a list sorted by date, and adds all /** Removes the first commit from a list sorted by date, and adds all

View File

@ -0,0 +1,144 @@
// 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)
@@
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)
@@
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)
@@
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);
@@
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);
@@
expression E;
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);
@@
expression E;
expression F;
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);

View File

@ -160,13 +160,20 @@ const char *loose_object_path(struct repository *r, struct strbuf *buf, const un
void *map_sha1_file(struct repository *r, const unsigned char *sha1, unsigned long *size); 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, enum object_type *type,
unsigned long *size, int lookup_replace); 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(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 */ /* 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 *); int oid_object_info(struct repository *r, const struct object_id *, unsigned long *);
@ -204,15 +211,27 @@ int read_loose_object(const char *path,
* object_info. OBJECT_INFO_SKIP_CACHED is automatically set; pass * object_info. OBJECT_INFO_SKIP_CACHED is automatically set; pass
* nonzero flags to also set other flags. * nonzero flags to also set other flags.
*/ */
extern int has_sha1_file_with_flags(const unsigned char *sha1, int flags); int repo_has_sha1_file_with_flags(struct repository *r,
static inline int has_sha1_file(const unsigned char *sha1) 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. */ /* Same as the above, except for struct object_id. */
extern int has_object_file(const struct object_id *oid); int repo_has_object_file(struct repository *r, const struct object_id *oid);
extern 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);
#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 * Return true iff an alternate object database has a loose object

View File

@ -259,8 +259,8 @@ struct object *parse_object(struct repository *r, const struct object_id *oid)
if (obj && obj->parsed) if (obj && obj->parsed)
return obj; return obj;
if ((obj && obj->type == OBJ_BLOB && has_object_file(oid)) || if ((obj && obj->type == OBJ_BLOB && repo_has_object_file(r, oid)) ||
(!obj && has_object_file(oid) && (!obj && repo_has_object_file(r, oid) &&
oid_object_info(r, oid, NULL) == OBJ_BLOB)) { oid_object_info(r, oid, NULL) == OBJ_BLOB)) {
if (check_object_signature(repl, NULL, 0, NULL) < 0) { if (check_object_signature(repl, NULL, 0, NULL) < 0) {
error(_("sha1 mismatch %s"), oid_to_hex(oid)); 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); 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 (buffer) {
if (check_object_signature(repl, buffer, size, type_name(type)) < 0) { if (check_object_signature(repl, buffer, size, type_name(type)) < 0) {
free(buffer); free(buffer);
@ -540,7 +540,7 @@ void parsed_object_pool_clear(struct parsed_object_pool *o)
if (obj->type == OBJ_TREE) if (obj->type == OBJ_TREE)
free_tree_buffer((struct tree*)obj); free_tree_buffer((struct tree*)obj);
else if (obj->type == OBJ_COMMIT) 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) else if (obj->type == OBJ_TAG)
release_tag_memory((struct tag*)obj); release_tag_memory((struct tag*)obj);
} }

View File

@ -1148,12 +1148,13 @@ void mark_bad_packed_object(struct packed_git *p, const unsigned char *sha1)
p->num_bad_objects++; 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; struct packed_git *p;
unsigned i; 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++) for (i = 0; i < p->num_bad_objects; i++)
if (hasheq(sha1, if (hasheq(sha1,
p->bad_object_sha1 + the_hash_algo->rawsz * i)) p->bad_object_sha1 + the_hash_algo->rawsz * i))

View File

@ -146,7 +146,7 @@ extern int packed_object_info(struct repository *r,
off_t offset, struct object_info *); off_t offset, struct object_info *);
extern void mark_bad_packed_object(struct packed_git *p, const unsigned char *sha1); 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, * Iff a pack file in the given repository contains the object named by sha1,

2
path.h
View File

@ -165,7 +165,7 @@ extern void report_linked_checkout_garbage(void);
const char *git_path_##var(struct repository *r) \ const char *git_path_##var(struct repository *r) \
{ \ { \
if (!r->cached_paths.var) \ 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; \ return r->cached_paths.var; \
} }

View File

@ -595,14 +595,15 @@ static char *replace_encoding_header(char *buf, const char *encoding)
return strbuf_detach(&tmp, NULL); return strbuf_detach(&tmp, NULL);
} }
const char *logmsg_reencode(const struct commit *commit, const char *repo_logmsg_reencode(struct repository *r,
char **commit_encoding, const struct commit *commit,
const char *output_encoding) char **commit_encoding,
const char *output_encoding)
{ {
static const char *utf8 = "UTF-8"; static const char *utf8 = "UTF-8";
const char *use_encoding; const char *use_encoding;
char *encoding; char *encoding;
const char *msg = get_commit_buffer(commit, NULL); const char *msg = repo_get_commit_buffer(r, commit, NULL);
char *out; char *out;
if (!output_encoding || !*output_encoding) { 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 * the cached copy from get_commit_buffer, we need to duplicate it
* to avoid munging the cached copy. * 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); out = xstrdup(msg);
else else
out = (char *)msg; out = (char *)msg;
@ -644,7 +645,7 @@ const char *logmsg_reencode(const struct commit *commit,
*/ */
out = reencode_string(msg, output_encoding, use_encoding); out = reencode_string(msg, output_encoding, use_encoding);
if (out) if (out)
unuse_commit_buffer(commit, msg); repo_unuse_commit_buffer(r, commit, msg);
} }
/* /*
@ -1527,9 +1528,10 @@ void userformat_find_requirements(const char *fmt, struct userformat_want *w)
strbuf_release(&dummy); strbuf_release(&dummy);
} }
void format_commit_message(const struct commit *commit, void repo_format_commit_message(struct repository *r,
const char *format, struct strbuf *sb, const struct commit *commit,
const struct pretty_print_context *pretty_ctx) const char *format, struct strbuf *sb,
const struct pretty_print_context *pretty_ctx)
{ {
struct format_commit_context context; struct format_commit_context context;
const char *output_enc = pretty_ctx->output_encoding; const char *output_enc = pretty_ctx->output_encoding;
@ -1543,9 +1545,9 @@ void format_commit_message(const struct commit *commit,
* convert a commit message to UTF-8 first * convert a commit message to UTF-8 first
* as far as 'format_commit_item' assumes it in UTF-8 * as far as 'format_commit_item' assumes it in UTF-8
*/ */
context.message = logmsg_reencode(commit, context.message = repo_logmsg_reencode(r, commit,
&context.commit_encoding, &context.commit_encoding,
utf8); utf8);
strbuf_expand(sb, format, format_commit_item, &context); strbuf_expand(sb, format, format_commit_item, &context);
rewrap_message_tail(sb, &context, 0, 0, 0); rewrap_message_tail(sb, &context, 0, 0, 0);
@ -1569,7 +1571,7 @@ void format_commit_message(const struct commit *commit,
} }
free(context.commit_encoding); 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, static void pp_header(struct pretty_print_context *pp,

View File

@ -104,9 +104,14 @@ void pp_remainder(struct pretty_print_context *pp, const char **msg_p,
* Put the result to "sb". * Put the result to "sb".
* Please use this function for custom formats. * 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 char *format, struct strbuf *sb,
const struct pretty_print_context *context); 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 * Parse given arguments from "arg", check it for correctness and

View File

@ -1421,7 +1421,9 @@ int oid_object_info(struct repository *r,
return type; 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) unsigned long *size)
{ {
struct object_id oid; struct object_id oid;
@ -1433,7 +1435,7 @@ static void *read_object(const unsigned char *sha1, enum object_type *type,
hashcpy(oid.hash, sha1); 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 NULL;
return content; return content;
} }
@ -1461,7 +1463,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 * deal with them should arrange to call read_object() and give error
* messages themselves. * 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, enum object_type *type,
unsigned long *size, unsigned long *size,
int lookup_replace) int lookup_replace)
@ -1471,10 +1474,10 @@ void *read_object_file_extended(const struct object_id *oid,
const char *path; const char *path;
struct stat st; struct stat st;
const struct object_id *repl = lookup_replace ? const struct object_id *repl = lookup_replace ?
lookup_replace_object(the_repository, oid) : oid; lookup_replace_object(r, oid) : oid;
errno = 0; errno = 0;
data = read_object(repl->hash, type, size); data = read_object(r, repl->hash, type, size);
if (data) if (data)
return data; return data;
@ -1486,11 +1489,11 @@ void *read_object_file_extended(const struct object_id *oid,
die(_("replacement %s not found for %s"), die(_("replacement %s not found for %s"),
oid_to_hex(repl), oid_to_hex(oid)); 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"), die(_("loose object %s (stored in %s) is corrupt"),
oid_to_hex(repl), path); oid_to_hex(repl), path);
if ((p = has_packed_and_bad(repl->hash)) != NULL) if ((p = has_packed_and_bad(r, repl->hash)) != NULL)
die(_("packed object %s (stored in %s) is corrupt"), die(_("packed object %s (stored in %s) is corrupt"),
oid_to_hex(repl), p->pack_name); oid_to_hex(repl), p->pack_name);
@ -1814,7 +1817,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
if (has_loose_object(oid)) if (has_loose_object(oid))
return 0; return 0;
buf = read_object(oid->hash, &type, &len); buf = read_object(the_repository, oid->hash, &type, &len);
if (!buf) if (!buf)
return error(_("cannot read sha1_file for %s"), oid_to_hex(oid)); return error(_("cannot read sha1_file for %s"), oid_to_hex(oid));
hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1; hdrlen = xsnprintf(hdr, sizeof(hdr), "%s %"PRIuMAX , type_name(type), (uintmax_t)len) + 1;
@ -1824,24 +1827,27 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
return ret; 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; struct object_id oid;
if (!startup_info->have_repository) if (!startup_info->have_repository)
return 0; return 0;
hashcpy(oid.hash, sha1); 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; 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) static void check_tree(const void *buf, size_t size)

View File

@ -499,7 +499,7 @@ static struct stream_vtbl incore_vtbl = {
static open_method_decl(incore) 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->u.incore.read_ptr = 0;
st->vtbl = &incore_vtbl; st->vtbl = &incore_vtbl;

View File

@ -456,7 +456,7 @@ static int prepare_submodule_summary(struct rev_info *rev, const char *path,
return prepare_revision_walk(rev); 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"; static const char format[] = " %m %s";
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
@ -467,7 +467,8 @@ static void print_submodule_summary(struct rev_info *rev, struct diff_options *o
ctx.date_mode = rev->date_mode; ctx.date_mode = rev->date_mode;
ctx.output_encoding = get_log_output_encoding(); ctx.output_encoding = get_log_output_encoding();
strbuf_setlen(&sb, 0); strbuf_setlen(&sb, 0);
format_commit_message(commit, format, &sb, &ctx); repo_format_commit_message(r, commit, format, &sb,
&ctx);
strbuf_addch(&sb, '\n'); strbuf_addch(&sb, '\n');
if (commit->object.flags & SYMMETRIC_LEFT) if (commit->object.flags & SYMMETRIC_LEFT)
diff_emit_submodule_del(o, sb.buf); diff_emit_submodule_del(o, sb.buf);
@ -500,14 +501,46 @@ static void prepare_submodule_repo_env_in_gitdir(struct argv_array *out)
argv_array_pushf(out, "%s=.", GIT_DIR_ENVIRONMENT); argv_array_pushf(out, "%s=.", 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 * Initialize a repository struct for a submodule based on the provided 'path'.
* attempt to lookup both the left and right commits and put them into the *
* left and right pointers. * 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, struct object_id *one, struct object_id *two,
unsigned dirty_submodule, unsigned dirty_submodule,
struct repository *sub,
struct commit **left, struct commit **right, struct commit **left, struct commit **right,
struct commit_list **merge_bases) struct commit_list **merge_bases)
{ {
@ -526,7 +559,7 @@ static void show_submodule_header(struct diff_options *o, const char *path,
else if (is_null_oid(two)) else if (is_null_oid(two))
message = "(submodule deleted)"; message = "(submodule deleted)";
if (add_submodule_odb(path)) { if (!sub) {
if (!message) if (!message)
message = "(commits not present)"; message = "(commits not present)";
goto output_header; goto output_header;
@ -536,8 +569,8 @@ static void show_submodule_header(struct diff_options *o, const char *path,
* Attempt to lookup the commit references, and determine if this is * Attempt to lookup the commit references, and determine if this is
* a fast forward or fast backwards update. * a fast forward or fast backwards update.
*/ */
*left = lookup_commit_reference(the_repository, one); *left = lookup_commit_reference(sub, one);
*right = lookup_commit_reference(the_repository, two); *right = lookup_commit_reference(sub, two);
/* /*
* Warn about missing commits in the submodule project, but only if * Warn about missing commits in the submodule project, but only if
@ -547,7 +580,7 @@ static void show_submodule_header(struct diff_options *o, const char *path,
(!is_null_oid(two) && !*right)) (!is_null_oid(two) && !*right))
message = "(commits not present)"; 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) {
if ((*merge_bases)->item == *left) if ((*merge_bases)->item == *left)
fast_forward = 1; fast_forward = 1;
@ -581,16 +614,18 @@ void show_submodule_summary(struct diff_options *o, const char *path,
struct rev_info rev; struct rev_info rev;
struct commit *left = NULL, *right = NULL; struct commit *left = NULL, *right = NULL;
struct commit_list *merge_bases = NULL; struct commit_list *merge_bases = NULL;
struct repository *sub;
sub = open_submodule(path);
show_submodule_header(o, path, one, two, dirty_submodule, 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 * 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 * reason to try and display a summary. The header line should contain
* all the information the user needs. * all the information the user needs.
*/ */
if (!left || !right) if (!left || !right || !sub)
goto out; goto out;
/* Treat revision walker failure the same as missing commits */ /* Treat revision walker failure the same as missing commits */
@ -599,13 +634,17 @@ void show_submodule_summary(struct diff_options *o, const char *path,
goto out; goto out;
} }
print_submodule_summary(&rev, o); print_submodule_summary(sub, &rev, o);
out: out:
if (merge_bases) if (merge_bases)
free_commit_list(merge_bases); free_commit_list(merge_bases);
clear_commit_marks(left, ~0); clear_commit_marks(left, ~0);
clear_commit_marks(right, ~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, void show_submodule_inline_diff(struct diff_options *o, const char *path,
@ -617,9 +656,11 @@ void show_submodule_inline_diff(struct diff_options *o, const char *path,
struct commit_list *merge_bases = NULL; struct commit_list *merge_bases = NULL;
struct child_process cp = CHILD_PROCESS_INIT; struct child_process cp = CHILD_PROCESS_INIT;
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
struct repository *sub;
sub = open_submodule(path);
show_submodule_header(o, path, one, two, dirty_submodule, 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 */ /* We need a valid left and right commit to display a difference */
if (!(left || is_null_oid(one)) || if (!(left || is_null_oid(one)) ||
@ -680,6 +721,10 @@ done:
clear_commit_marks(left, ~0); clear_commit_marks(left, ~0);
if (right) if (right)
clear_commit_marks(right, ~0); clear_commit_marks(right, ~0);
if (sub) {
repo_clear(sub);
free(sub);
}
} }
int should_update_submodules(void) int should_update_submodules(void)
@ -1004,9 +1049,6 @@ static int push_submodule(const char *path,
const struct string_list *push_options, const struct string_list *push_options,
int dry_run) int dry_run)
{ {
if (add_submodule_odb(path))
return 1;
if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) { if (for_each_remote_ref_submodule(path, has_remote, NULL) > 0) {
struct child_process cp = CHILD_PROCESS_INIT; struct child_process cp = CHILD_PROCESS_INIT;
argv_array_push(&cp.args, "push"); argv_array_push(&cp.args, "push");

View File

@ -17,6 +17,11 @@ static void test_parse_commit_in_graph(const char *gitdir, const char *worktree,
setup_git_env(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)) if (repo_init(&r, gitdir, worktree))
die("Couldn't init repo"); die("Couldn't init repo");
@ -43,6 +48,11 @@ static void test_get_commit_tree_in_graph(const char *gitdir,
setup_git_env(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)) if (repo_init(&r, gitdir, worktree))
die("Couldn't init repo"); die("Couldn't init repo");