aboutsummaryrefslogtreecommitdiffstats
path: root/odb.c
diff options
context:
space:
mode:
Diffstat (limited to 'odb.c')
-rw-r--r--odb.c225
1 files changed, 155 insertions, 70 deletions
diff --git a/odb.c b/odb.c
index 00a6e71568..af13174425 100644
--- a/odb.c
+++ b/odb.c
@@ -1,5 +1,6 @@
#include "git-compat-util.h"
#include "abspath.h"
+#include "chdir-notify.h"
#include "commit-graph.h"
#include "config.h"
#include "dir.h"
@@ -9,6 +10,7 @@
#include "khash.h"
#include "lockfile.h"
#include "loose.h"
+#include "midx.h"
#include "object-file-convert.h"
#include "object-file.h"
#include "odb.h"
@@ -22,6 +24,7 @@
#include "strbuf.h"
#include "strvec.h"
#include "submodule.h"
+#include "tmp-objdir.h"
#include "trace2.h"
#include "write-or-die.h"
@@ -86,17 +89,16 @@ int odb_mkstemp(struct object_database *odb,
/*
* Return non-zero iff the path is usable as an alternate object database.
*/
-static int alt_odb_usable(struct object_database *o,
- struct strbuf *path,
- const char *normalized_objdir, khiter_t *pos)
+static int alt_odb_usable(struct object_database *o, const char *path,
+ const char *normalized_objdir)
{
int r;
/* Detect cases where alternate disappeared */
- if (!is_directory(path->buf)) {
+ if (!is_directory(path)) {
error(_("object directory %s does not exist; "
"check .git/objects/info/alternates"),
- path->buf);
+ path);
return 0;
}
@@ -113,11 +115,14 @@ static int alt_odb_usable(struct object_database *o,
assert(r == 1); /* never used */
kh_value(o->source_by_path, p) = o->sources;
}
- if (fspatheq(path->buf, normalized_objdir))
+
+ if (fspatheq(path, normalized_objdir))
+ return 0;
+
+ if (kh_get_odb_path_map(o->source_by_path, path) < kh_end(o->source_by_path))
return 0;
- *pos = kh_put_odb_path_map(o->source_by_path, path->buf, &r);
- /* r: 0 = exists, 1 = never used, 2 = deleted */
- return r == 0 ? 0 : 1;
+
+ return 1;
}
/*
@@ -139,6 +144,21 @@ static void read_info_alternates(struct object_database *odb,
const char *relative_base,
int depth);
+static struct odb_source *odb_source_new(struct object_database *odb,
+ const char *path,
+ bool local)
+{
+ struct odb_source *source;
+
+ CALLOC_ARRAY(source, 1);
+ source->odb = odb;
+ source->local = local;
+ source->path = xstrdup(path);
+ source->loose = odb_source_loose_new(source);
+
+ return source;
+}
+
static struct odb_source *link_alt_odb_entry(struct object_database *odb,
const char *dir,
const char *relative_base,
@@ -148,6 +168,7 @@ static struct odb_source *link_alt_odb_entry(struct object_database *odb,
struct strbuf pathbuf = STRBUF_INIT;
struct strbuf tmp = STRBUF_INIT;
khiter_t pos;
+ int ret;
if (!is_absolute_path(dir) && relative_base) {
strbuf_realpath(&pathbuf, relative_base, 1);
@@ -172,20 +193,18 @@ static struct odb_source *link_alt_odb_entry(struct object_database *odb,
strbuf_reset(&tmp);
strbuf_realpath(&tmp, odb->sources->path, 1);
- if (!alt_odb_usable(odb, &pathbuf, tmp.buf, &pos))
+ if (!alt_odb_usable(odb, pathbuf.buf, tmp.buf))
goto error;
- CALLOC_ARRAY(alternate, 1);
- alternate->odb = odb;
- alternate->local = false;
- /* pathbuf.buf is already in r->objects->source_by_path */
- alternate->path = strbuf_detach(&pathbuf, NULL);
+ alternate = odb_source_new(odb, pathbuf.buf, false);
/* add the alternate entry */
*odb->sources_tail = alternate;
odb->sources_tail = &(alternate->next);
- alternate->next = NULL;
- assert(odb->source_by_path);
+
+ pos = kh_put_odb_path_map(odb->source_by_path, alternate->path, &ret);
+ if (!ret)
+ BUG("source must not yet exist");
kh_value(odb->source_by_path, pos) = alternate;
/* recursively add alternates */
@@ -337,26 +356,23 @@ struct odb_source *odb_set_temporary_primary_source(struct object_database *odb,
* Make a new primary odb and link the old primary ODB in as an
* alternate
*/
- source = xcalloc(1, sizeof(*source));
- source->odb = odb;
- source->path = xstrdup(dir);
+ source = odb_source_new(odb, dir, false);
/*
* Disable ref updates while a temporary odb is active, since
* the objects in the database may roll back.
*/
- source->disable_ref_updates = 1;
+ odb->repo->disable_ref_updates = true;
source->will_destroy = will_destroy;
source->next = odb->sources;
odb->sources = source;
return source->next;
}
-static void free_object_directory(struct odb_source *source)
+static void odb_source_free(struct odb_source *source)
{
free(source->path);
- odb_clear_loose_cache(source);
- loose_object_map_clear(&source->loose_map);
+ odb_source_loose_free(source->loose);
free(source);
}
@@ -373,8 +389,9 @@ void odb_restore_primary_source(struct object_database *odb,
if (cur_source->next != restore_source)
BUG("we expect the old primary object store to be the first alternate");
+ odb->repo->disable_ref_updates = false;
odb->sources = restore_source;
- free_object_directory(cur_source);
+ odb_source_free(cur_source);
}
char *compute_alternate_path(const char *path, struct strbuf *err)
@@ -653,8 +670,6 @@ static int do_oid_object_info_extended(struct object_database *odb,
{
static struct object_info blank_oi = OBJECT_INFO_INIT;
const struct cached_object *co;
- struct pack_entry e;
- int rtype;
const struct object_id *real = oid;
int already_retried = 0;
@@ -684,19 +699,24 @@ static int do_oid_object_info_extended(struct object_database *odb,
return 0;
}
+ odb_prepare_alternates(odb);
+
while (1) {
- if (find_pack_entry(odb->repo, real, &e))
- break;
+ struct odb_source *source;
- /* Most likely it's a loose object. */
- if (!loose_object_info(odb->repo, real, oi, flags))
+ if (!packfile_store_read_object_info(odb->packfiles, real, oi, flags))
return 0;
+ /* Most likely it's a loose object. */
+ for (source = odb->sources; source; source = source->next)
+ if (!odb_source_loose_read_object_info(source, real, oi, flags))
+ return 0;
+
/* Not a loose object; someone else may have just packed it. */
if (!(flags & OBJECT_INFO_QUICK)) {
odb_reprepare(odb->repo->objects);
- if (find_pack_entry(odb->repo, real, &e))
- break;
+ if (!packfile_store_read_object_info(odb->packfiles, real, oi, flags))
+ return 0;
}
/*
@@ -729,25 +749,6 @@ static int do_oid_object_info_extended(struct object_database *odb,
}
return -1;
}
-
- if (oi == &blank_oi)
- /*
- * We know that the caller doesn't actually need the
- * information below, so return early.
- */
- return 0;
- rtype = packed_object_info(odb->repo, e.p, e.offset, oi);
- if (rtype < 0) {
- mark_bad_packed_object(e.p, real);
- return do_oid_object_info_extended(odb, real, oi, 0);
- } else if (oi->whence == OI_PACKED) {
- oi->u.packed.offset = e.offset;
- oi->u.packed.pack = e.p;
- oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA ||
- rtype == OBJ_OFS_DELTA);
- }
-
- return 0;
}
static int oid_object_info_convert(struct repository *r,
@@ -969,6 +970,22 @@ int odb_has_object(struct object_database *odb, const struct object_id *oid,
return odb_read_object_info_extended(odb, oid, NULL, object_info_flags) >= 0;
}
+int odb_freshen_object(struct object_database *odb,
+ const struct object_id *oid)
+{
+ struct odb_source *source;
+
+ if (packfile_store_freshen_object(odb->packfiles, oid))
+ return 1;
+
+ odb_prepare_alternates(odb);
+ for (source = odb->sources; source; source = source->next)
+ if (odb_source_loose_freshen_object(source, oid))
+ return 1;
+
+ return 0;
+}
+
void odb_assert_oid_type(struct object_database *odb,
const struct object_id *oid, enum object_type expect)
{
@@ -987,58 +1004,126 @@ int odb_write_object_ext(struct object_database *odb,
struct object_id *compat_oid,
unsigned flags)
{
- return write_object_file(odb->sources, buf, len, type, oid, compat_oid, flags);
+ return odb_source_loose_write_object(odb->sources, buf, len, type,
+ oid, compat_oid, flags);
}
-struct object_database *odb_new(struct repository *repo)
+int odb_write_object_stream(struct object_database *odb,
+ struct odb_write_stream *stream, size_t len,
+ struct object_id *oid)
+{
+ return odb_source_loose_write_stream(odb->sources, stream, len, oid);
+}
+
+static void odb_update_commondir(const char *name UNUSED,
+ const char *old_cwd,
+ const char *new_cwd,
+ void *cb_data)
+{
+ struct object_database *odb = cb_data;
+ struct tmp_objdir *tmp_objdir;
+ struct odb_source *source;
+
+ tmp_objdir = tmp_objdir_unapply_primary_odb();
+
+ /*
+ * In theory, we only have to do this for the primary object source, as
+ * alternates' paths are always resolved to an absolute path.
+ */
+ for (source = odb->sources; source; source = source->next) {
+ char *path;
+
+ if (is_absolute_path(source->path))
+ continue;
+
+ path = reparent_relative_path(old_cwd, new_cwd,
+ source->path);
+
+ free(source->path);
+ source->path = path;
+ }
+
+ if (tmp_objdir)
+ tmp_objdir_reapply_primary_odb(tmp_objdir, old_cwd, new_cwd);
+}
+
+struct object_database *odb_new(struct repository *repo,
+ const char *primary_source,
+ const char *secondary_sources)
{
struct object_database *o = xmalloc(sizeof(*o));
+ char *to_free = NULL;
memset(o, 0, sizeof(*o));
o->repo = repo;
o->packfiles = packfile_store_new(o);
pthread_mutex_init(&o->replace_mutex, NULL);
string_list_init_dup(&o->submodule_source_paths);
+
+ if (!primary_source)
+ primary_source = to_free = xstrfmt("%s/objects", repo->commondir);
+ o->sources = odb_source_new(o, primary_source, true);
+ o->sources_tail = &o->sources->next;
+ o->alternate_db = xstrdup_or_null(secondary_sources);
+
+ free(to_free);
+
+ chdir_notify_register(NULL, odb_update_commondir, o);
+
return o;
}
-static void free_object_directories(struct object_database *o)
+void odb_close(struct object_database *o)
+{
+ struct odb_source *source;
+
+ packfile_store_close(o->packfiles);
+
+ for (source = o->sources; source; source = source->next) {
+ if (source->midx)
+ close_midx(source->midx);
+ source->midx = NULL;
+ }
+
+ close_commit_graph(o);
+}
+
+static void odb_free_sources(struct object_database *o)
{
while (o->sources) {
struct odb_source *next;
next = o->sources->next;
- free_object_directory(o->sources);
+ odb_source_free(o->sources);
o->sources = next;
}
kh_destroy_odb_path_map(o->source_by_path);
o->source_by_path = NULL;
}
-void odb_clear(struct object_database *o)
+void odb_free(struct object_database *o)
{
- FREE_AND_NULL(o->alternate_db);
+ if (!o)
+ return;
+
+ free(o->alternate_db);
oidmap_clear(&o->replace_map, 1);
pthread_mutex_destroy(&o->replace_mutex);
- free_commit_graph(o->commit_graph);
- o->commit_graph = NULL;
- o->commit_graph_attempted = 0;
-
- free_object_directories(o);
- o->sources_tail = NULL;
- o->loaded_alternates = 0;
+ odb_free_sources(o);
for (size_t i = 0; i < o->cached_object_nr; i++)
free((char *) o->cached_objects[i].value.buf);
- FREE_AND_NULL(o->cached_objects);
+ free(o->cached_objects);
- close_object_store(o);
+ odb_close(o);
packfile_store_free(o->packfiles);
- o->packfiles = NULL;
-
string_list_clear(&o->submodule_source_paths, 0);
+
+ chdir_notify_unregister(NULL, odb_update_commondir, o);
+
+ free(o);
}
void odb_reprepare(struct object_database *o)
@@ -1057,7 +1142,7 @@ void odb_reprepare(struct object_database *o)
odb_prepare_alternates(o);
for (source = o->sources; source; source = source->next)
- odb_clear_loose_cache(source);
+ odb_source_loose_reprepare(source);
o->approximate_object_count_valid = 0;