summaryrefslogtreecommitdiff
path: root/sha1-file.c
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2018-11-12 14:50:39 (GMT)
committerJunio C Hamano <gitster@pobox.com>2018-11-13 05:22:03 (GMT)
commitf0eaf638195a6510254b075026dcad955b8b607d (patch)
tree405fd2aeb1e4384f0df3166aef14304145c1370d /sha1-file.c
parentf3f043a103b7a7da57272ecf3252bda6089e41ae (diff)
downloadgit-f0eaf638195a6510254b075026dcad955b8b607d.zip
git-f0eaf638195a6510254b075026dcad955b8b607d.tar.gz
git-f0eaf638195a6510254b075026dcad955b8b607d.tar.bz2
sha1-file: use an object_directory for the main object dir
Our handling of alternate object directories is needlessly different from the main object directory. As a result, many places in the code basically look like this: do_something(r->objects->objdir); for (odb = r->objects->alt_odb_list; odb; odb = odb->next) do_something(odb->path); That gets annoying when do_something() is non-trivial, and we've resorted to gross hacks like creating fake alternates (see find_short_object_filename()). Instead, let's give each raw_object_store a unified list of object_directory structs. The first will be the main store, and everything after is an alternate. Very few callers even care about the distinction, and can just loop over the whole list (and those who care can just treat the first element differently). A few observations: - we don't need r->objects->objectdir anymore, and can just mechanically convert that to r->objects->odb->path - object_directory's path field needs to become a real pointer rather than a FLEX_ARRAY, in order to fill it with expand_base_dir() - we'll call prepare_alt_odb() earlier in many functions (i.e., outside of the loop). This may result in us calling it even when our function would be satisfied looking only at the main odb. But this doesn't matter in practice. It's not a very expensive operation in the first place, and in the majority of cases it will be a noop. We call it already (and cache its results) in prepare_packed_git(), and we'll generally check packs before loose objects. So essentially every program is going to call it immediately once per program. Arguably we should just prepare_alt_odb() immediately upon setting up the repository's object directory, which would save us sprinkling calls throughout the code base (and forgetting to do so has been a source of subtle bugs in the past). But I've stopped short of that here, since there are already a lot of other moving parts in this patch. - Most call sites just get shorter. The check_and_freshen() functions are an exception, because they have entry points to handle local and nonlocal directories separately. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'sha1-file.c')
-rw-r--r--sha1-file.c122
1 files changed, 44 insertions, 78 deletions
diff --git a/sha1-file.c b/sha1-file.c
index 15db6b6..503262e 100644
--- a/sha1-file.c
+++ b/sha1-file.c
@@ -346,11 +346,12 @@ static void fill_sha1_path(struct strbuf *buf, const unsigned char *sha1)
}
}
-static const char *odb_loose_path(const char *path, struct strbuf *buf,
+static const char *odb_loose_path(struct object_directory *odb,
+ struct strbuf *buf,
const unsigned char *sha1)
{
strbuf_reset(buf);
- strbuf_addstr(buf, path);
+ strbuf_addstr(buf, odb->path);
strbuf_addch(buf, '/');
fill_sha1_path(buf, sha1);
return buf->buf;
@@ -359,7 +360,7 @@ static const char *odb_loose_path(const char *path, struct strbuf *buf,
const char *loose_object_path(struct repository *r, struct strbuf *buf,
const unsigned char *sha1)
{
- return odb_loose_path(r->objects->objectdir, buf, sha1);
+ return odb_loose_path(r->objects->odb, buf, sha1);
}
/*
@@ -383,7 +384,7 @@ static int alt_odb_usable(struct raw_object_store *o,
* Prevent the common mistake of listing the same
* thing twice, or object directory itself.
*/
- for (odb = o->alt_odb_list; odb; odb = odb->next) {
+ for (odb = o->odb; odb; odb = odb->next) {
if (!fspathcmp(path->buf, odb->path))
return 0;
}
@@ -442,11 +443,12 @@ static int link_alt_odb_entry(struct repository *r, const char *entry,
return -1;
}
- ent = alloc_alt_odb(pathbuf.buf);
+ ent = xcalloc(1, sizeof(*ent));
+ ent->path = xstrdup(pathbuf.buf);
/* add the alternate entry */
- *r->objects->alt_odb_tail = ent;
- r->objects->alt_odb_tail = &(ent->next);
+ *r->objects->odb_tail = ent;
+ r->objects->odb_tail = &(ent->next);
ent->next = NULL;
/* recursively add alternates */
@@ -500,7 +502,7 @@ static void link_alt_odb_entries(struct repository *r, const char *alt,
return;
}
- strbuf_add_absolute_path(&objdirbuf, r->objects->objectdir);
+ strbuf_add_absolute_path(&objdirbuf, r->objects->odb->path);
if (strbuf_normalize_path(&objdirbuf) < 0)
die(_("unable to normalize object directory: %s"),
objdirbuf.buf);
@@ -535,15 +537,6 @@ static void read_info_alternates(struct repository *r,
free(path);
}
-struct object_directory *alloc_alt_odb(const char *dir)
-{
- struct object_directory *ent;
-
- FLEX_ALLOC_STR(ent, path, dir);
-
- return ent;
-}
-
void add_to_alternates_file(const char *reference)
{
struct lock_file lock = LOCK_INIT;
@@ -580,7 +573,7 @@ void add_to_alternates_file(const char *reference)
fprintf_or_die(out, "%s\n", reference);
if (commit_lock_file(&lock))
die_errno(_("unable to move new alternates file into place"));
- if (the_repository->objects->alt_odb_tail)
+ if (the_repository->objects->loaded_alternates)
link_alt_odb_entries(the_repository, reference,
'\n', NULL, 0);
}
@@ -680,7 +673,7 @@ int foreach_alt_odb(alt_odb_fn fn, void *cb)
int r = 0;
prepare_alt_odb(the_repository);
- for (ent = the_repository->objects->alt_odb_list; ent; ent = ent->next) {
+ for (ent = the_repository->objects->odb->next; ent; ent = ent->next) {
r = fn(ent, cb);
if (r)
break;
@@ -690,13 +683,13 @@ int foreach_alt_odb(alt_odb_fn fn, void *cb)
void prepare_alt_odb(struct repository *r)
{
- if (r->objects->alt_odb_tail)
+ if (r->objects->loaded_alternates)
return;
- r->objects->alt_odb_tail = &r->objects->alt_odb_list;
link_alt_odb_entries(r, r->objects->alternate_db, PATH_SEP, NULL, 0);
- read_info_alternates(r, r->objects->objectdir, 0);
+ read_info_alternates(r, r->objects->odb->path, 0);
+ r->objects->loaded_alternates = 1;
}
/* Returns 1 if we have successfully freshened the file, 0 otherwise. */
@@ -723,24 +716,27 @@ int check_and_freshen_file(const char *fn, int freshen)
return 1;
}
-static int check_and_freshen_local(const struct object_id *oid, int freshen)
+static int check_and_freshen_odb(struct object_directory *odb,
+ const struct object_id *oid,
+ int freshen)
{
- static struct strbuf buf = STRBUF_INIT;
-
- loose_object_path(the_repository, &buf, oid->hash);
+ static struct strbuf path = STRBUF_INIT;
+ odb_loose_path(odb, &path, oid->hash);
+ return check_and_freshen_file(path.buf, freshen);
+}
- return check_and_freshen_file(buf.buf, freshen);
+static int check_and_freshen_local(const struct object_id *oid, int freshen)
+{
+ return check_and_freshen_odb(the_repository->objects->odb, oid, freshen);
}
static int check_and_freshen_nonlocal(const struct object_id *oid, int freshen)
{
struct object_directory *odb;
- static struct strbuf path = STRBUF_INIT;
prepare_alt_odb(the_repository);
- for (odb = the_repository->objects->alt_odb_list; odb; odb = odb->next) {
- odb_loose_path(odb->path, &path, oid->hash);
- if (check_and_freshen_file(path.buf, freshen))
+ for (odb = the_repository->objects->odb->next; odb; odb = odb->next) {
+ if (check_and_freshen_odb(odb, oid, freshen))
return 1;
}
return 0;
@@ -889,14 +885,9 @@ static int stat_sha1_file(struct repository *r, const unsigned char *sha1,
struct object_directory *odb;
static struct strbuf buf = STRBUF_INIT;
- *path = loose_object_path(r, &buf, sha1);
- if (!lstat(*path, st))
- return 0;
-
prepare_alt_odb(r);
- errno = ENOENT;
- for (odb = r->objects->alt_odb_list; odb; odb = odb->next) {
- *path = odb_loose_path(odb->path, &buf, sha1);
+ for (odb = r->objects->odb; odb; odb = odb->next) {
+ *path = odb_loose_path(odb, &buf, sha1);
if (!lstat(*path, st))
return 0;
}
@@ -913,21 +904,16 @@ static int open_sha1_file(struct repository *r,
{
int fd;
struct object_directory *odb;
- int most_interesting_errno;
+ int most_interesting_errno = ENOENT;
static struct strbuf buf = STRBUF_INIT;
- *path = loose_object_path(r, &buf, sha1);
- fd = git_open(*path);
- if (fd >= 0)
- return fd;
- most_interesting_errno = errno;
-
prepare_alt_odb(r);
- for (odb = r->objects->alt_odb_list; odb; odb = odb->next) {
- *path = odb_loose_path(odb->path, &buf, sha1);
+ for (odb = r->objects->odb; odb; odb = odb->next) {
+ *path = odb_loose_path(odb, &buf, sha1);
fd = git_open(*path);
if (fd >= 0)
return fd;
+
if (most_interesting_errno == ENOENT)
most_interesting_errno = errno;
}
@@ -2120,43 +2106,23 @@ int for_each_loose_file_in_objdir(const char *path,
return r;
}
-struct loose_alt_odb_data {
- each_loose_object_fn *cb;
- void *data;
-};
-
-static int loose_from_alt_odb(struct object_directory *odb,
- void *vdata)
-{
- struct loose_alt_odb_data *data = vdata;
- struct strbuf buf = STRBUF_INIT;
- int r;
-
- strbuf_addstr(&buf, odb->path);
- r = for_each_loose_file_in_objdir_buf(&buf,
- data->cb, NULL, NULL,
- data->data);
- strbuf_release(&buf);
- return r;
-}
-
int for_each_loose_object(each_loose_object_fn cb, void *data,
enum for_each_object_flags flags)
{
- struct loose_alt_odb_data alt;
- int r;
+ struct object_directory *odb;
- r = for_each_loose_file_in_objdir(get_object_directory(),
- cb, NULL, NULL, data);
- if (r)
- return r;
+ prepare_alt_odb(the_repository);
+ for (odb = the_repository->objects->odb; odb; odb = odb->next) {
+ int r = for_each_loose_file_in_objdir(odb->path, cb, NULL,
+ NULL, data);
+ if (r)
+ return r;
- if (flags & FOR_EACH_OBJECT_LOCAL_ONLY)
- return 0;
+ if (flags & FOR_EACH_OBJECT_LOCAL_ONLY)
+ break;
+ }
- alt.cb = cb;
- alt.data = data;
- return foreach_alt_odb(loose_from_alt_odb, &alt);
+ return 0;
}
static int check_stream_sha1(git_zstream *stream,