Skip to content

Commit 597f913

Browse files
peffgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 29ec6af commit 597f913

File tree

6 files changed

+24
-37
lines changed

6 files changed

+24
-37
lines changed

builtin/fsck.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -644,14 +644,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
644644
fsck_object_dir(get_object_directory());
645645

646646
prepare_alt_odb();
647-
for (alt = alt_odb_list; alt; alt = alt->next) {
648-
/* directory name, minus trailing slash */
649-
size_t namelen = alt->name - alt->base - 1;
650-
struct strbuf name = STRBUF_INIT;
651-
strbuf_add(&name, alt->base, namelen);
652-
fsck_object_dir(name.buf);
653-
strbuf_release(&name);
654-
}
647+
for (alt = alt_odb_list; alt; alt = alt->next)
648+
fsck_object_dir(alt->path);
655649
}
656650

657651
if (check_full) {

builtin/submodule--helper.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -492,20 +492,16 @@ static int add_possible_reference_from_superproject(
492492
{
493493
struct submodule_alternate_setup *sas = sas_cb;
494494

495-
/* directory name, minus trailing slash */
496-
size_t namelen = alt->name - alt->base - 1;
497-
struct strbuf name = STRBUF_INIT;
498-
strbuf_add(&name, alt->base, namelen);
499-
500495
/*
501496
* If the alternate object store is another repository, try the
502497
* standard layout with .git/modules/<name>/objects
503498
*/
504-
if (ends_with(name.buf, ".git/objects")) {
499+
if (ends_with(alt->path, ".git/objects")) {
505500
char *sm_alternate;
506501
struct strbuf sb = STRBUF_INIT;
507502
struct strbuf err = STRBUF_INIT;
508-
strbuf_add(&sb, name.buf, name.len - strlen("objects"));
503+
strbuf_add(&sb, alt->path, strlen(alt->path) - strlen("objects"));
504+
509505
/*
510506
* We need to end the new path with '/' to mark it as a dir,
511507
* otherwise a submodule name containing '/' will be broken
@@ -533,7 +529,6 @@ static int add_possible_reference_from_superproject(
533529
strbuf_release(&sb);
534530
}
535531

536-
strbuf_release(&name);
537532
return 0;
538533
}
539534

cache.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1383,8 +1383,11 @@ extern void remove_scheduled_dirs(void);
13831383

13841384
extern struct alternate_object_database {
13851385
struct alternate_object_database *next;
1386+
13861387
char *name;
1387-
char base[FLEX_ARRAY]; /* more */
1388+
char *scratch;
1389+
1390+
char path[FLEX_ARRAY];
13881391
} *alt_odb_list;
13891392
extern void prepare_alt_odb(void);
13901393
extern void read_info_alternates(const char * relative_base, int depth);

sha1_file.c

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ static const char *alt_sha1_path(struct alternate_object_database *alt,
208208
const unsigned char *sha1)
209209
{
210210
fill_sha1_path(alt->name, sha1);
211-
return alt->base;
211+
return alt->scratch;
212212
}
213213

214214
/*
@@ -261,8 +261,7 @@ static int alt_odb_usable(struct strbuf *path, const char *normalized_objdir)
261261
* thing twice, or object directory itself.
262262
*/
263263
for (alt = alt_odb_list; alt; alt = alt->next) {
264-
if (path->len == alt->name - alt->base - 1 &&
265-
!memcmp(path->buf, alt->base, path->len))
264+
if (!strcmp(path->buf, alt->path))
266265
return 0;
267266
}
268267
if (!fspathcmp(path->buf, normalized_objdir))
@@ -401,13 +400,14 @@ struct alternate_object_database *alloc_alt_odb(const char *dir)
401400
size_t entlen;
402401

403402
entlen = st_add(dirlen, 43); /* '/' + 2 hex + '/' + 38 hex + NUL */
404-
ent = xmalloc(st_add(sizeof(*ent), entlen));
405-
memcpy(ent->base, dir, dirlen);
403+
FLEX_ALLOC_STR(ent, path, dir);
404+
ent->scratch = xmalloc(entlen);
405+
xsnprintf(ent->scratch, entlen, "%s/", dir);
406406

407-
ent->name = ent->base + dirlen + 1;
408-
ent->base[dirlen] = '/';
409-
ent->base[dirlen + 3] = '/';
410-
ent->base[entlen-1] = 0;
407+
ent->name = ent->scratch + dirlen + 1;
408+
ent->scratch[dirlen] = '/';
409+
ent->scratch[dirlen + 3] = '/';
410+
ent->scratch[entlen-1] = 0;
411411

412412
return ent;
413413
}
@@ -1485,11 +1485,8 @@ void prepare_packed_git(void)
14851485
return;
14861486
prepare_packed_git_one(get_object_directory(), 1);
14871487
prepare_alt_odb();
1488-
for (alt = alt_odb_list; alt; alt = alt->next) {
1489-
alt->name[-1] = 0;
1490-
prepare_packed_git_one(alt->base, 0);
1491-
alt->name[-1] = '/';
1492-
}
1488+
for (alt = alt_odb_list; alt; alt = alt->next)
1489+
prepare_packed_git_one(alt->path, 0);
14931490
rearrange_packed_git();
14941491
prepare_packed_git_mru();
14951492
prepare_packed_git_run_once = 1;
@@ -3692,8 +3689,7 @@ static int loose_from_alt_odb(struct alternate_object_database *alt,
36923689
struct strbuf buf = STRBUF_INIT;
36933690
int r;
36943691

3695-
/* copy base not including trailing '/' */
3696-
strbuf_add(&buf, alt->base, alt->name - alt->base - 1);
3692+
strbuf_addstr(&buf, alt->path);
36973693
r = for_each_loose_file_in_objdir_buf(&buf,
36983694
data->cb, NULL, NULL,
36993695
data->data);

sha1_name.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,13 @@ static void find_short_object_filename(int len, const char *hex_pfx, struct disa
9494
for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) {
9595
struct dirent *de;
9696
DIR *dir;
97+
9798
/*
9899
* every alt_odb struct has 42 extra bytes after the base
99100
* for exactly this purpose
100101
*/
101102
xsnprintf(alt->name, 42, "%.2s/", hex_pfx);
102-
dir = opendir(alt->base);
103+
dir = opendir(alt->scratch);
103104
if (!dir)
104105
continue;
105106

transport.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,9 +1084,7 @@ static int refs_from_alternate_cb(struct alternate_object_database *e,
10841084
const struct ref *extra;
10851085
struct alternate_refs_data *cb = data;
10861086

1087-
e->name[-1] = '\0';
1088-
other = xstrdup(real_path(e->base));
1089-
e->name[-1] = '/';
1087+
other = xstrdup(real_path(e->path));
10901088
len = strlen(other);
10911089

10921090
while (other[len-1] == '/')

0 commit comments

Comments
 (0)