Revision 85fe0e800ca6acc690fc4c55931a200b4679211e authored by Johannes Schindelin on 31 July 2019, 20:06:42 UTC, committed by Junio C Hamano on 31 July 2019, 22:20:56 UTC
Since 07b2c0eacac (config: learn the "onbranch:" includeIf condition, 2019-06-05), there is a potential catch-22 in the early config path: if the `include.onbranch:` feature is used, Git assumes that the Git directory has been initialized already. However, in the early config code path that is not true. One way to trigger this is to call the following commands in any repository: git config includeif.onbranch:refs/heads/master.path broken git help -a The symptom triggered by the `git help -a` invocation reads like this: BUG: refs.c:1851: attempting to get main_ref_store outside of repository Let's work around this, simply by ignoring the `includeif.onbranch:` setting when parsing the config when the ref store has not been initialized (yet). Technically, there is a way to solve this properly: teach the refs machinery to initialize the ref_store from a given gitdir/commondir pair (which we _do_ have in the early config code path), and then use that in `include_by_branch()`. This, however, is a pretty involved project, and we're already in the feature freeze for Git v2.23.0. Note: when calling above-mentioned two commands _outside_ of any Git worktree (passing the `--global` flag to `git config`, as there is obviously no repository config available), at the point when `include_by_branch()` is called, `the_repository` is `NULL`, therefore we have to be extra careful not to dereference it in that case. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent f36d08d
alloc.c
/*
* alloc.c - specialized allocator for internal objects
*
* Copyright (C) 2006 Linus Torvalds
*
* The standard malloc/free wastes too much space for objects, partly because
* it maintains all the allocation infrastructure, but even more because it ends
* up with maximal alignment because it doesn't know what the object alignment
* for the new allocation is.
*/
#include "cache.h"
#include "object.h"
#include "blob.h"
#include "tree.h"
#include "commit.h"
#include "tag.h"
#include "alloc.h"
#define BLOCKING 1024
union any_object {
struct object object;
struct blob blob;
struct tree tree;
struct commit commit;
struct tag tag;
};
struct alloc_state {
int count; /* total number of nodes allocated */
int nr; /* number of nodes left in current allocation */
void *p; /* first free node in current allocation */
/* bookkeeping of allocations */
void **slabs;
int slab_nr, slab_alloc;
};
struct alloc_state *allocate_alloc_state(void)
{
return xcalloc(1, sizeof(struct alloc_state));
}
void clear_alloc_state(struct alloc_state *s)
{
while (s->slab_nr > 0) {
s->slab_nr--;
free(s->slabs[s->slab_nr]);
}
FREE_AND_NULL(s->slabs);
}
static inline void *alloc_node(struct alloc_state *s, size_t node_size)
{
void *ret;
if (!s->nr) {
s->nr = BLOCKING;
s->p = xmalloc(BLOCKING * node_size);
ALLOC_GROW(s->slabs, s->slab_nr + 1, s->slab_alloc);
s->slabs[s->slab_nr++] = s->p;
}
s->nr--;
s->count++;
ret = s->p;
s->p = (char *)s->p + node_size;
memset(ret, 0, node_size);
return ret;
}
void *alloc_blob_node(struct repository *r)
{
struct blob *b = alloc_node(r->parsed_objects->blob_state, sizeof(struct blob));
b->object.type = OBJ_BLOB;
return b;
}
void *alloc_tree_node(struct repository *r)
{
struct tree *t = alloc_node(r->parsed_objects->tree_state, sizeof(struct tree));
t->object.type = OBJ_TREE;
return t;
}
void *alloc_tag_node(struct repository *r)
{
struct tag *t = alloc_node(r->parsed_objects->tag_state, sizeof(struct tag));
t->object.type = OBJ_TAG;
return t;
}
void *alloc_object_node(struct repository *r)
{
struct object *obj = alloc_node(r->parsed_objects->object_state, sizeof(union any_object));
obj->type = OBJ_NONE;
return obj;
}
static unsigned int alloc_commit_index(struct repository *r)
{
return r->parsed_objects->commit_count++;
}
void init_commit_node(struct repository *r, struct commit *c)
{
c->object.type = OBJ_COMMIT;
c->index = alloc_commit_index(r);
c->graph_pos = COMMIT_NOT_FROM_GRAPH;
c->generation = GENERATION_NUMBER_INFINITY;
}
void *alloc_commit_node(struct repository *r)
{
struct commit *c = alloc_node(r->parsed_objects->commit_state, sizeof(struct commit));
init_commit_node(r, c);
return c;
}
static void report(const char *name, unsigned int count, size_t size)
{
fprintf(stderr, "%10s: %8u (%"PRIuMAX" kB)\n",
name, count, (uintmax_t) size);
}
#define REPORT(name, type) \
report(#name, r->parsed_objects->name##_state->count, \
r->parsed_objects->name##_state->count * sizeof(type) >> 10)
void alloc_report(struct repository *r)
{
REPORT(blob, struct blob);
REPORT(tree, struct tree);
REPORT(commit, struct commit);
REPORT(tag, struct tag);
REPORT(object, union any_object);
}
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...