alternates: use a separate scratch space
The alternate_object_database struct uses a single buffer both for storing the path to the alternate, and as a scratch buffer for forming object names. This is efficient (since otherwise we'd end up storing the path twice), but it makes life hard for callers who just want to know the path to the alternate. They have to remember to stop reading after "alt->name - alt->base" bytes, and to subtract one for the trailing '/'. It would be much simpler if they could simply access a NUL-terminated path string. We could encapsulate this in a function which puts a NUL in the scratch buffer and returns the string, but that opens up questions about the lifetime of the result. The first time another caller uses the alternate, the scratch buffer may get other data tacked onto it. Let's instead just store the root path separately from the scratch buffer. There aren't enough alternates being stored for the duplicated data to matter for performance, and this keeps things simple and safe for the callers. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
29ec6af2b8
commit
597f9134de
@ -644,14 +644,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||||||
fsck_object_dir(get_object_directory());
|
fsck_object_dir(get_object_directory());
|
||||||
|
|
||||||
prepare_alt_odb();
|
prepare_alt_odb();
|
||||||
for (alt = alt_odb_list; alt; alt = alt->next) {
|
for (alt = alt_odb_list; alt; alt = alt->next)
|
||||||
/* directory name, minus trailing slash */
|
fsck_object_dir(alt->path);
|
||||||
size_t namelen = alt->name - alt->base - 1;
|
|
||||||
struct strbuf name = STRBUF_INIT;
|
|
||||||
strbuf_add(&name, alt->base, namelen);
|
|
||||||
fsck_object_dir(name.buf);
|
|
||||||
strbuf_release(&name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (check_full) {
|
if (check_full) {
|
||||||
|
@ -492,20 +492,16 @@ static int add_possible_reference_from_superproject(
|
|||||||
{
|
{
|
||||||
struct submodule_alternate_setup *sas = sas_cb;
|
struct submodule_alternate_setup *sas = sas_cb;
|
||||||
|
|
||||||
/* directory name, minus trailing slash */
|
|
||||||
size_t namelen = alt->name - alt->base - 1;
|
|
||||||
struct strbuf name = STRBUF_INIT;
|
|
||||||
strbuf_add(&name, alt->base, namelen);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the alternate object store is another repository, try the
|
* If the alternate object store is another repository, try the
|
||||||
* standard layout with .git/modules/<name>/objects
|
* standard layout with .git/modules/<name>/objects
|
||||||
*/
|
*/
|
||||||
if (ends_with(name.buf, ".git/objects")) {
|
if (ends_with(alt->path, ".git/objects")) {
|
||||||
char *sm_alternate;
|
char *sm_alternate;
|
||||||
struct strbuf sb = STRBUF_INIT;
|
struct strbuf sb = STRBUF_INIT;
|
||||||
struct strbuf err = STRBUF_INIT;
|
struct strbuf err = STRBUF_INIT;
|
||||||
strbuf_add(&sb, name.buf, name.len - strlen("objects"));
|
strbuf_add(&sb, alt->path, strlen(alt->path) - strlen("objects"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to end the new path with '/' to mark it as a dir,
|
* We need to end the new path with '/' to mark it as a dir,
|
||||||
* otherwise a submodule name containing '/' will be broken
|
* otherwise a submodule name containing '/' will be broken
|
||||||
@ -533,7 +529,6 @@ static int add_possible_reference_from_superproject(
|
|||||||
strbuf_release(&sb);
|
strbuf_release(&sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
strbuf_release(&name);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
cache.h
5
cache.h
@ -1383,8 +1383,11 @@ extern void remove_scheduled_dirs(void);
|
|||||||
|
|
||||||
extern struct alternate_object_database {
|
extern struct alternate_object_database {
|
||||||
struct alternate_object_database *next;
|
struct alternate_object_database *next;
|
||||||
|
|
||||||
char *name;
|
char *name;
|
||||||
char base[FLEX_ARRAY]; /* more */
|
char *scratch;
|
||||||
|
|
||||||
|
char path[FLEX_ARRAY];
|
||||||
} *alt_odb_list;
|
} *alt_odb_list;
|
||||||
extern void prepare_alt_odb(void);
|
extern void prepare_alt_odb(void);
|
||||||
extern void read_info_alternates(const char * relative_base, int depth);
|
extern void read_info_alternates(const char * relative_base, int depth);
|
||||||
|
28
sha1_file.c
28
sha1_file.c
@ -208,7 +208,7 @@ static const char *alt_sha1_path(struct alternate_object_database *alt,
|
|||||||
const unsigned char *sha1)
|
const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
fill_sha1_path(alt->name, sha1);
|
fill_sha1_path(alt->name, sha1);
|
||||||
return alt->base;
|
return alt->scratch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -261,8 +261,7 @@ static int alt_odb_usable(struct strbuf *path, const char *normalized_objdir)
|
|||||||
* thing twice, or object directory itself.
|
* thing twice, or object directory itself.
|
||||||
*/
|
*/
|
||||||
for (alt = alt_odb_list; alt; alt = alt->next) {
|
for (alt = alt_odb_list; alt; alt = alt->next) {
|
||||||
if (path->len == alt->name - alt->base - 1 &&
|
if (!strcmp(path->buf, alt->path))
|
||||||
!memcmp(path->buf, alt->base, path->len))
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!fspathcmp(path->buf, normalized_objdir))
|
if (!fspathcmp(path->buf, normalized_objdir))
|
||||||
@ -401,13 +400,14 @@ struct alternate_object_database *alloc_alt_odb(const char *dir)
|
|||||||
size_t entlen;
|
size_t entlen;
|
||||||
|
|
||||||
entlen = st_add(dirlen, 43); /* '/' + 2 hex + '/' + 38 hex + NUL */
|
entlen = st_add(dirlen, 43); /* '/' + 2 hex + '/' + 38 hex + NUL */
|
||||||
ent = xmalloc(st_add(sizeof(*ent), entlen));
|
FLEX_ALLOC_STR(ent, path, dir);
|
||||||
memcpy(ent->base, dir, dirlen);
|
ent->scratch = xmalloc(entlen);
|
||||||
|
xsnprintf(ent->scratch, entlen, "%s/", dir);
|
||||||
|
|
||||||
ent->name = ent->base + dirlen + 1;
|
ent->name = ent->scratch + dirlen + 1;
|
||||||
ent->base[dirlen] = '/';
|
ent->scratch[dirlen] = '/';
|
||||||
ent->base[dirlen + 3] = '/';
|
ent->scratch[dirlen + 3] = '/';
|
||||||
ent->base[entlen-1] = 0;
|
ent->scratch[entlen-1] = 0;
|
||||||
|
|
||||||
return ent;
|
return ent;
|
||||||
}
|
}
|
||||||
@ -1485,11 +1485,8 @@ void prepare_packed_git(void)
|
|||||||
return;
|
return;
|
||||||
prepare_packed_git_one(get_object_directory(), 1);
|
prepare_packed_git_one(get_object_directory(), 1);
|
||||||
prepare_alt_odb();
|
prepare_alt_odb();
|
||||||
for (alt = alt_odb_list; alt; alt = alt->next) {
|
for (alt = alt_odb_list; alt; alt = alt->next)
|
||||||
alt->name[-1] = 0;
|
prepare_packed_git_one(alt->path, 0);
|
||||||
prepare_packed_git_one(alt->base, 0);
|
|
||||||
alt->name[-1] = '/';
|
|
||||||
}
|
|
||||||
rearrange_packed_git();
|
rearrange_packed_git();
|
||||||
prepare_packed_git_mru();
|
prepare_packed_git_mru();
|
||||||
prepare_packed_git_run_once = 1;
|
prepare_packed_git_run_once = 1;
|
||||||
@ -3692,8 +3689,7 @@ static int loose_from_alt_odb(struct alternate_object_database *alt,
|
|||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* copy base not including trailing '/' */
|
strbuf_addstr(&buf, alt->path);
|
||||||
strbuf_add(&buf, alt->base, alt->name - alt->base - 1);
|
|
||||||
r = for_each_loose_file_in_objdir_buf(&buf,
|
r = for_each_loose_file_in_objdir_buf(&buf,
|
||||||
data->cb, NULL, NULL,
|
data->cb, NULL, NULL,
|
||||||
data->data);
|
data->data);
|
||||||
|
@ -94,12 +94,13 @@ static void find_short_object_filename(int len, const char *hex_pfx, struct disa
|
|||||||
for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) {
|
for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) {
|
||||||
struct dirent *de;
|
struct dirent *de;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* every alt_odb struct has 42 extra bytes after the base
|
* every alt_odb struct has 42 extra bytes after the base
|
||||||
* for exactly this purpose
|
* for exactly this purpose
|
||||||
*/
|
*/
|
||||||
xsnprintf(alt->name, 42, "%.2s/", hex_pfx);
|
xsnprintf(alt->name, 42, "%.2s/", hex_pfx);
|
||||||
dir = opendir(alt->base);
|
dir = opendir(alt->scratch);
|
||||||
if (!dir)
|
if (!dir)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -1084,9 +1084,7 @@ static int refs_from_alternate_cb(struct alternate_object_database *e,
|
|||||||
const struct ref *extra;
|
const struct ref *extra;
|
||||||
struct alternate_refs_data *cb = data;
|
struct alternate_refs_data *cb = data;
|
||||||
|
|
||||||
e->name[-1] = '\0';
|
other = xstrdup(real_path(e->path));
|
||||||
other = xstrdup(real_path(e->base));
|
|
||||||
e->name[-1] = '/';
|
|
||||||
len = strlen(other);
|
len = strlen(other);
|
||||||
|
|
||||||
while (other[len-1] == '/')
|
while (other[len-1] == '/')
|
||||||
|
Loading…
Reference in New Issue
Block a user