Merge branch 'jk/loose-object-cache'
Code clean-up with optimization for the codepath that checks (non-)existence of loose objects. * jk/loose-object-cache: odb_load_loose_cache: fix strbuf leak fetch-pack: drop custom loose object cache sha1-file: use loose object cache for quick existence check object-store: provide helpers for loose_objects_cache sha1-file: use an object_directory for the main object dir handle alternates paths the same as the main object dir sha1_file_name(): overwrite buffer instead of appending rename "alternate_object_database" to "object_directory" submodule--helper: prefer strip_suffix() to ends_with() fsck: do not reuse child_process structs
This commit is contained in:
commit
3b2f8a02fa
@ -78,10 +78,10 @@ static int count_cruft(const char *basename, const char *path, void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int print_alternate(struct alternate_object_database *alt, void *data)
|
static int print_alternate(struct object_directory *odb, void *data)
|
||||||
{
|
{
|
||||||
printf("alternate: ");
|
printf("alternate: ");
|
||||||
quote_c_style(alt->path, NULL, stdout, 0);
|
quote_c_style(odb->path, NULL, stdout, 0);
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -739,7 +739,7 @@ static struct option fsck_opts[] = {
|
|||||||
int cmd_fsck(int argc, const char **argv, const char *prefix)
|
int cmd_fsck(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct alternate_object_database *alt;
|
struct object_directory *odb;
|
||||||
|
|
||||||
/* fsck knows how to handle missing promisor objects */
|
/* fsck knows how to handle missing promisor objects */
|
||||||
fetch_if_missing = 0;
|
fetch_if_missing = 0;
|
||||||
@ -775,14 +775,9 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||||||
for_each_loose_object(mark_loose_for_connectivity, NULL, 0);
|
for_each_loose_object(mark_loose_for_connectivity, NULL, 0);
|
||||||
for_each_packed_object(mark_packed_for_connectivity, NULL, 0);
|
for_each_packed_object(mark_packed_for_connectivity, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
struct alternate_object_database *alt_odb_list;
|
|
||||||
|
|
||||||
fsck_object_dir(get_object_directory());
|
|
||||||
|
|
||||||
prepare_alt_odb(the_repository);
|
prepare_alt_odb(the_repository);
|
||||||
alt_odb_list = the_repository->objects->alt_odb_list;
|
for (odb = the_repository->objects->odb; odb; odb = odb->next)
|
||||||
for (alt = alt_odb_list; alt; alt = alt->next)
|
fsck_object_dir(odb->path);
|
||||||
fsck_object_dir(alt->path);
|
|
||||||
|
|
||||||
if (check_full) {
|
if (check_full) {
|
||||||
struct packed_git *p;
|
struct packed_git *p;
|
||||||
@ -884,15 +879,13 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||||||
struct child_process commit_graph_verify = CHILD_PROCESS_INIT;
|
struct child_process commit_graph_verify = CHILD_PROCESS_INIT;
|
||||||
const char *verify_argv[] = { "commit-graph", "verify", NULL, NULL, NULL };
|
const char *verify_argv[] = { "commit-graph", "verify", NULL, NULL, NULL };
|
||||||
|
|
||||||
commit_graph_verify.argv = verify_argv;
|
|
||||||
commit_graph_verify.git_cmd = 1;
|
|
||||||
if (run_command(&commit_graph_verify))
|
|
||||||
errors_found |= ERROR_COMMIT_GRAPH;
|
|
||||||
|
|
||||||
prepare_alt_odb(the_repository);
|
prepare_alt_odb(the_repository);
|
||||||
for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next) {
|
for (odb = the_repository->objects->odb; odb; odb = odb->next) {
|
||||||
|
child_process_init(&commit_graph_verify);
|
||||||
|
commit_graph_verify.argv = verify_argv;
|
||||||
|
commit_graph_verify.git_cmd = 1;
|
||||||
verify_argv[2] = "--object-dir";
|
verify_argv[2] = "--object-dir";
|
||||||
verify_argv[3] = alt->path;
|
verify_argv[3] = odb->path;
|
||||||
if (run_command(&commit_graph_verify))
|
if (run_command(&commit_graph_verify))
|
||||||
errors_found |= ERROR_COMMIT_GRAPH;
|
errors_found |= ERROR_COMMIT_GRAPH;
|
||||||
}
|
}
|
||||||
@ -902,15 +895,13 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||||||
struct child_process midx_verify = CHILD_PROCESS_INIT;
|
struct child_process midx_verify = CHILD_PROCESS_INIT;
|
||||||
const char *midx_argv[] = { "multi-pack-index", "verify", NULL, NULL, NULL };
|
const char *midx_argv[] = { "multi-pack-index", "verify", NULL, NULL, NULL };
|
||||||
|
|
||||||
midx_verify.argv = midx_argv;
|
|
||||||
midx_verify.git_cmd = 1;
|
|
||||||
if (run_command(&midx_verify))
|
|
||||||
errors_found |= ERROR_COMMIT_GRAPH;
|
|
||||||
|
|
||||||
prepare_alt_odb(the_repository);
|
prepare_alt_odb(the_repository);
|
||||||
for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next) {
|
for (odb = the_repository->objects->odb; odb; odb = odb->next) {
|
||||||
|
child_process_init(&midx_verify);
|
||||||
|
midx_verify.argv = midx_argv;
|
||||||
|
midx_verify.git_cmd = 1;
|
||||||
midx_argv[2] = "--object-dir";
|
midx_argv[2] = "--object-dir";
|
||||||
midx_argv[3] = alt->path;
|
midx_argv[3] = odb->path;
|
||||||
if (run_command(&midx_verify))
|
if (run_command(&midx_verify))
|
||||||
errors_found |= ERROR_COMMIT_GRAPH;
|
errors_found |= ERROR_COMMIT_GRAPH;
|
||||||
}
|
}
|
||||||
|
@ -437,7 +437,7 @@ static int grep_submodule(struct grep_opt *opt, struct repository *superproject,
|
|||||||
* store is no longer global and instead is a member of the repository
|
* store is no longer global and instead is a member of the repository
|
||||||
* object.
|
* object.
|
||||||
*/
|
*/
|
||||||
add_to_alternates_memory(submodule.objects->objectdir);
|
add_to_alternates_memory(submodule.objects->odb->path);
|
||||||
grep_read_unlock();
|
grep_read_unlock();
|
||||||
|
|
||||||
if (oid) {
|
if (oid) {
|
||||||
|
@ -1265,19 +1265,20 @@ struct submodule_alternate_setup {
|
|||||||
SUBMODULE_ALTERNATE_ERROR_IGNORE, NULL }
|
SUBMODULE_ALTERNATE_ERROR_IGNORE, NULL }
|
||||||
|
|
||||||
static int add_possible_reference_from_superproject(
|
static int add_possible_reference_from_superproject(
|
||||||
struct alternate_object_database *alt, void *sas_cb)
|
struct object_directory *odb, void *sas_cb)
|
||||||
{
|
{
|
||||||
struct submodule_alternate_setup *sas = sas_cb;
|
struct submodule_alternate_setup *sas = sas_cb;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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(alt->path, "/objects")) {
|
if (strip_suffix(odb->path, "/objects", &len)) {
|
||||||
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, alt->path, strlen(alt->path) - strlen("objects"));
|
strbuf_add(&sb, odb->path, len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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,
|
||||||
@ -1285,7 +1286,7 @@ static int add_possible_reference_from_superproject(
|
|||||||
* as the last part of a missing submodule reference would
|
* as the last part of a missing submodule reference would
|
||||||
* be taken as a file name.
|
* be taken as a file name.
|
||||||
*/
|
*/
|
||||||
strbuf_addf(&sb, "modules/%s/", sas->submodule_name);
|
strbuf_addf(&sb, "/modules/%s/", sas->submodule_name);
|
||||||
|
|
||||||
sm_alternate = compute_alternate_path(sb.buf, &err);
|
sm_alternate = compute_alternate_path(sb.buf, &err);
|
||||||
if (sm_alternate) {
|
if (sm_alternate) {
|
||||||
|
@ -230,8 +230,7 @@ static void prepare_commit_graph_one(struct repository *r, const char *obj_dir)
|
|||||||
*/
|
*/
|
||||||
static int prepare_commit_graph(struct repository *r)
|
static int prepare_commit_graph(struct repository *r)
|
||||||
{
|
{
|
||||||
struct alternate_object_database *alt;
|
struct object_directory *odb;
|
||||||
char *obj_dir;
|
|
||||||
int config_value;
|
int config_value;
|
||||||
|
|
||||||
if (r->objects->commit_graph_attempted)
|
if (r->objects->commit_graph_attempted)
|
||||||
@ -252,13 +251,11 @@ static int prepare_commit_graph(struct repository *r)
|
|||||||
if (!commit_graph_compatible(r))
|
if (!commit_graph_compatible(r))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
obj_dir = r->objects->objectdir;
|
|
||||||
prepare_commit_graph_one(r, obj_dir);
|
|
||||||
prepare_alt_odb(r);
|
prepare_alt_odb(r);
|
||||||
for (alt = r->objects->alt_odb_list;
|
for (odb = r->objects->odb;
|
||||||
!r->objects->commit_graph && alt;
|
!r->objects->commit_graph && odb;
|
||||||
alt = alt->next)
|
odb = odb->next)
|
||||||
prepare_commit_graph_one(r, alt->path);
|
prepare_commit_graph_one(r, odb->path);
|
||||||
return !!r->objects->commit_graph;
|
return !!r->objects->commit_graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,9 +274,9 @@ const char *get_git_work_tree(void)
|
|||||||
|
|
||||||
char *get_object_directory(void)
|
char *get_object_directory(void)
|
||||||
{
|
{
|
||||||
if (!the_repository->objects->objectdir)
|
if (!the_repository->objects->odb)
|
||||||
BUG("git environment hasn't been setup");
|
BUG("git environment hasn't been setup");
|
||||||
return the_repository->objects->objectdir;
|
return the_repository->objects->odb->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
|
int odb_mkstemp(struct strbuf *temp_filename, const char *pattern)
|
||||||
|
39
fetch-pack.c
39
fetch-pack.c
@ -636,23 +636,6 @@ struct loose_object_iter {
|
|||||||
struct ref *refs;
|
struct ref *refs;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* If the number of refs is not larger than the number of loose objects,
|
|
||||||
* this function stops inserting.
|
|
||||||
*/
|
|
||||||
static int add_loose_objects_to_set(const struct object_id *oid,
|
|
||||||
const char *path,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
struct loose_object_iter *iter = data;
|
|
||||||
oidset_insert(iter->loose_object_set, oid);
|
|
||||||
if (iter->refs == NULL)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
iter->refs = iter->refs->next;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark recent commits available locally and reachable from a local ref as
|
* Mark recent commits available locally and reachable from a local ref as
|
||||||
* COMPLETE. If args->no_dependents is false, also mark COMPLETE remote refs as
|
* COMPLETE. If args->no_dependents is false, also mark COMPLETE remote refs as
|
||||||
@ -670,30 +653,14 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
|
|||||||
struct ref *ref;
|
struct ref *ref;
|
||||||
int old_save_commit_buffer = save_commit_buffer;
|
int old_save_commit_buffer = save_commit_buffer;
|
||||||
timestamp_t cutoff = 0;
|
timestamp_t cutoff = 0;
|
||||||
struct oidset loose_oid_set = OIDSET_INIT;
|
|
||||||
int use_oidset = 0;
|
|
||||||
struct loose_object_iter iter = {&loose_oid_set, *refs};
|
|
||||||
|
|
||||||
/* Enumerate all loose objects or know refs are not so many. */
|
|
||||||
use_oidset = !for_each_loose_object(add_loose_objects_to_set,
|
|
||||||
&iter, 0);
|
|
||||||
|
|
||||||
save_commit_buffer = 0;
|
save_commit_buffer = 0;
|
||||||
|
|
||||||
for (ref = *refs; ref; ref = ref->next) {
|
for (ref = *refs; ref; ref = ref->next) {
|
||||||
struct object *o;
|
struct object *o;
|
||||||
unsigned int flags = OBJECT_INFO_QUICK;
|
|
||||||
|
|
||||||
if (use_oidset &&
|
if (!has_object_file_with_flags(&ref->old_oid,
|
||||||
!oidset_contains(&loose_oid_set, &ref->old_oid)) {
|
OBJECT_INFO_QUICK))
|
||||||
/*
|
|
||||||
* I know this does not exist in the loose form,
|
|
||||||
* so check if it exists in a non-loose form.
|
|
||||||
*/
|
|
||||||
flags |= OBJECT_INFO_IGNORE_LOOSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!has_object_file_with_flags(&ref->old_oid, flags))
|
|
||||||
continue;
|
continue;
|
||||||
o = parse_object(the_repository, &ref->old_oid);
|
o = parse_object(the_repository, &ref->old_oid);
|
||||||
if (!o)
|
if (!o)
|
||||||
@ -710,8 +677,6 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
oidset_clear(&loose_oid_set);
|
|
||||||
|
|
||||||
if (!args->deepen) {
|
if (!args->deepen) {
|
||||||
for_each_ref(mark_complete_oid, NULL);
|
for_each_ref(mark_complete_oid, NULL);
|
||||||
for_each_cached_alternate(NULL, mark_alternate_complete);
|
for_each_cached_alternate(NULL, mark_alternate_complete);
|
||||||
|
@ -547,7 +547,7 @@ static int fetch_object(struct walker *walker, unsigned char *sha1)
|
|||||||
ret = error("File %s has bad hash", hex);
|
ret = error("File %s has bad hash", hex);
|
||||||
} else if (req->rename < 0) {
|
} else if (req->rename < 0) {
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
sha1_file_name(the_repository, &buf, req->sha1);
|
loose_object_path(the_repository, &buf, req->sha1);
|
||||||
ret = error("unable to write sha1 filename %s", buf.buf);
|
ret = error("unable to write sha1 filename %s", buf.buf);
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
}
|
}
|
||||||
|
4
http.c
4
http.c
@ -2353,7 +2353,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
|
|||||||
hashcpy(freq->sha1, sha1);
|
hashcpy(freq->sha1, sha1);
|
||||||
freq->localfile = -1;
|
freq->localfile = -1;
|
||||||
|
|
||||||
sha1_file_name(the_repository, &filename, sha1);
|
loose_object_path(the_repository, &filename, sha1);
|
||||||
strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf);
|
strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf);
|
||||||
|
|
||||||
strbuf_addf(&prevfile, "%s.prev", filename.buf);
|
strbuf_addf(&prevfile, "%s.prev", filename.buf);
|
||||||
@ -2504,7 +2504,7 @@ int finish_http_object_request(struct http_object_request *freq)
|
|||||||
unlink_or_warn(freq->tmpfile.buf);
|
unlink_or_warn(freq->tmpfile.buf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sha1_file_name(the_repository, &filename, freq->sha1);
|
loose_object_path(the_repository, &filename, freq->sha1);
|
||||||
freq->rename = finalize_object_file(freq->tmpfile.buf, filename.buf);
|
freq->rename = finalize_object_file(freq->tmpfile.buf, filename.buf);
|
||||||
strbuf_release(&filename);
|
strbuf_release(&filename);
|
||||||
|
|
||||||
|
2
midx.c
2
midx.c
@ -931,7 +931,7 @@ cleanup:
|
|||||||
|
|
||||||
void clear_midx_file(struct repository *r)
|
void clear_midx_file(struct repository *r)
|
||||||
{
|
{
|
||||||
char *midx = get_midx_filename(r->objects->objectdir);
|
char *midx = get_midx_filename(r->objects->odb->path);
|
||||||
|
|
||||||
if (r->objects && r->objects->multi_pack_index) {
|
if (r->objects && r->objects->multi_pack_index) {
|
||||||
close_midx(r->objects->multi_pack_index);
|
close_midx(r->objects->multi_pack_index);
|
||||||
|
@ -7,19 +7,17 @@
|
|||||||
#include "sha1-array.h"
|
#include "sha1-array.h"
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
|
|
||||||
struct alternate_object_database {
|
struct object_directory {
|
||||||
struct alternate_object_database *next;
|
struct object_directory *next;
|
||||||
|
|
||||||
/* see alt_scratch_buf() */
|
|
||||||
struct strbuf scratch;
|
|
||||||
size_t base_len;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used to store the results of readdir(3) calls when searching
|
* Used to store the results of readdir(3) calls when we are OK
|
||||||
* for unique abbreviated hashes. This cache is never
|
* sacrificing accuracy due to races for speed. That includes
|
||||||
* invalidated, thus it's racy and not necessarily accurate.
|
* object existence with OBJECT_INFO_QUICK, as well as
|
||||||
* That's fine for its purpose; don't use it for tasks requiring
|
* our search for unique abbreviated hashes. Don't use it for tasks
|
||||||
* greater accuracy!
|
* requiring greater accuracy!
|
||||||
|
*
|
||||||
|
* Be sure to call odb_load_loose_cache() before using.
|
||||||
*/
|
*/
|
||||||
char loose_objects_subdir_seen[256];
|
char loose_objects_subdir_seen[256];
|
||||||
struct oid_array loose_objects_cache;
|
struct oid_array loose_objects_cache;
|
||||||
@ -28,19 +26,14 @@ struct alternate_object_database {
|
|||||||
* Path to the alternative object store. If this is a relative path,
|
* Path to the alternative object store. If this is a relative path,
|
||||||
* it is relative to the current working directory.
|
* it is relative to the current working directory.
|
||||||
*/
|
*/
|
||||||
char path[FLEX_ARRAY];
|
char *path;
|
||||||
};
|
};
|
||||||
|
|
||||||
void prepare_alt_odb(struct repository *r);
|
void prepare_alt_odb(struct repository *r);
|
||||||
char *compute_alternate_path(const char *path, struct strbuf *err);
|
char *compute_alternate_path(const char *path, struct strbuf *err);
|
||||||
typedef int alt_odb_fn(struct alternate_object_database *, void *);
|
typedef int alt_odb_fn(struct object_directory *, void *);
|
||||||
int foreach_alt_odb(alt_odb_fn, void*);
|
int foreach_alt_odb(alt_odb_fn, void*);
|
||||||
|
|
||||||
/*
|
|
||||||
* Allocate a "struct alternate_object_database" but do _not_ actually
|
|
||||||
* add it to the list of alternates.
|
|
||||||
*/
|
|
||||||
struct alternate_object_database *alloc_alt_odb(const char *dir);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the directory to the on-disk alternates file; the new entry will also
|
* Add the directory to the on-disk alternates file; the new entry will also
|
||||||
* take effect in the current process.
|
* take effect in the current process.
|
||||||
@ -55,12 +48,11 @@ void add_to_alternates_file(const char *dir);
|
|||||||
void add_to_alternates_memory(const char *dir);
|
void add_to_alternates_memory(const char *dir);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns a scratch strbuf pre-filled with the alternate object directory,
|
* Populate an odb's loose object cache for one particular subdirectory (i.e.,
|
||||||
* including a trailing slash, which can be used to access paths in the
|
* the one that corresponds to the first byte of objects you're interested in,
|
||||||
* alternate. Always use this over direct access to alt->scratch, as it
|
* from 0 to 255 inclusive).
|
||||||
* cleans up any previous use of the scratch buffer.
|
|
||||||
*/
|
*/
|
||||||
struct strbuf *alt_scratch_buf(struct alternate_object_database *alt);
|
void odb_load_loose_cache(struct object_directory *odb, int subdir_nr);
|
||||||
|
|
||||||
struct packed_git {
|
struct packed_git {
|
||||||
struct packed_git *next;
|
struct packed_git *next;
|
||||||
@ -92,17 +84,21 @@ struct multi_pack_index;
|
|||||||
|
|
||||||
struct raw_object_store {
|
struct raw_object_store {
|
||||||
/*
|
/*
|
||||||
* Path to the repository's object store.
|
* Set of all object directories; the main directory is first (and
|
||||||
* Cannot be NULL after initialization.
|
* cannot be NULL after initialization). Subsequent directories are
|
||||||
|
* alternates.
|
||||||
*/
|
*/
|
||||||
char *objectdir;
|
struct object_directory *odb;
|
||||||
|
struct object_directory **odb_tail;
|
||||||
|
int loaded_alternates;
|
||||||
|
|
||||||
/* Path to extra alternate object database if not NULL */
|
/*
|
||||||
|
* A list of alternate object directories loaded from the environment;
|
||||||
|
* this should not generally need to be accessed directly, but will
|
||||||
|
* populate the "odb" list when prepare_alt_odb() is run.
|
||||||
|
*/
|
||||||
char *alternate_db;
|
char *alternate_db;
|
||||||
|
|
||||||
struct alternate_object_database *alt_odb_list;
|
|
||||||
struct alternate_object_database **alt_odb_tail;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Objects that should be substituted by other objects
|
* Objects that should be substituted by other objects
|
||||||
* (see git-replace(1)).
|
* (see git-replace(1)).
|
||||||
@ -157,7 +153,7 @@ void raw_object_store_clear(struct raw_object_store *o);
|
|||||||
* Put in `buf` the name of the file in the local object database that
|
* Put in `buf` the name of the file in the local object database that
|
||||||
* would be used to store a loose object with the specified sha1.
|
* would be used to store a loose object with the specified sha1.
|
||||||
*/
|
*/
|
||||||
void sha1_file_name(struct repository *r, struct strbuf *buf, const unsigned char *sha1);
|
const char *loose_object_path(struct repository *r, struct strbuf *buf, const unsigned char *sha1);
|
||||||
|
|
||||||
void *map_sha1_file(struct repository *r, const unsigned char *sha1, unsigned long *size);
|
void *map_sha1_file(struct repository *r, const unsigned char *sha1, unsigned long *size);
|
||||||
|
|
||||||
|
26
object.c
26
object.c
@ -482,27 +482,26 @@ struct raw_object_store *raw_object_store_new(void)
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_alt_odb(struct alternate_object_database *alt)
|
static void free_object_directory(struct object_directory *odb)
|
||||||
{
|
{
|
||||||
strbuf_release(&alt->scratch);
|
free(odb->path);
|
||||||
oid_array_clear(&alt->loose_objects_cache);
|
oid_array_clear(&odb->loose_objects_cache);
|
||||||
free(alt);
|
free(odb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_alt_odbs(struct raw_object_store *o)
|
static void free_object_directories(struct raw_object_store *o)
|
||||||
{
|
{
|
||||||
while (o->alt_odb_list) {
|
while (o->odb) {
|
||||||
struct alternate_object_database *next;
|
struct object_directory *next;
|
||||||
|
|
||||||
next = o->alt_odb_list->next;
|
next = o->odb->next;
|
||||||
free_alt_odb(o->alt_odb_list);
|
free_object_directory(o->odb);
|
||||||
o->alt_odb_list = next;
|
o->odb = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void raw_object_store_clear(struct raw_object_store *o)
|
void raw_object_store_clear(struct raw_object_store *o)
|
||||||
{
|
{
|
||||||
FREE_AND_NULL(o->objectdir);
|
|
||||||
FREE_AND_NULL(o->alternate_db);
|
FREE_AND_NULL(o->alternate_db);
|
||||||
|
|
||||||
oidmap_free(o->replace_map, 1);
|
oidmap_free(o->replace_map, 1);
|
||||||
@ -512,8 +511,9 @@ void raw_object_store_clear(struct raw_object_store *o)
|
|||||||
o->commit_graph = NULL;
|
o->commit_graph = NULL;
|
||||||
o->commit_graph_attempted = 0;
|
o->commit_graph_attempted = 0;
|
||||||
|
|
||||||
free_alt_odbs(o);
|
free_object_directories(o);
|
||||||
o->alt_odb_tail = NULL;
|
o->odb_tail = NULL;
|
||||||
|
o->loaded_alternates = 0;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&o->packed_git_mru);
|
INIT_LIST_HEAD(&o->packed_git_mru);
|
||||||
close_all_packs(o);
|
close_all_packs(o);
|
||||||
|
20
packfile.c
20
packfile.c
@ -971,16 +971,16 @@ static void prepare_packed_git_mru(struct repository *r)
|
|||||||
|
|
||||||
static void prepare_packed_git(struct repository *r)
|
static void prepare_packed_git(struct repository *r)
|
||||||
{
|
{
|
||||||
struct alternate_object_database *alt;
|
struct object_directory *odb;
|
||||||
|
|
||||||
if (r->objects->packed_git_initialized)
|
if (r->objects->packed_git_initialized)
|
||||||
return;
|
return;
|
||||||
prepare_multi_pack_index_one(r, r->objects->objectdir, 1);
|
|
||||||
prepare_packed_git_one(r, r->objects->objectdir, 1);
|
|
||||||
prepare_alt_odb(r);
|
prepare_alt_odb(r);
|
||||||
for (alt = r->objects->alt_odb_list; alt; alt = alt->next) {
|
for (odb = r->objects->odb; odb; odb = odb->next) {
|
||||||
prepare_multi_pack_index_one(r, alt->path, 0);
|
int local = (odb == r->objects->odb);
|
||||||
prepare_packed_git_one(r, alt->path, 0);
|
prepare_multi_pack_index_one(r, odb->path, local);
|
||||||
|
prepare_packed_git_one(r, odb->path, local);
|
||||||
}
|
}
|
||||||
rearrange_packed_git(r);
|
rearrange_packed_git(r);
|
||||||
|
|
||||||
@ -992,6 +992,14 @@ static void prepare_packed_git(struct repository *r)
|
|||||||
|
|
||||||
void reprepare_packed_git(struct repository *r)
|
void reprepare_packed_git(struct repository *r)
|
||||||
{
|
{
|
||||||
|
struct object_directory *odb;
|
||||||
|
|
||||||
|
for (odb = r->objects->odb; odb; odb = odb->next) {
|
||||||
|
oid_array_clear(&odb->loose_objects_cache);
|
||||||
|
memset(&odb->loose_objects_subdir_seen, 0,
|
||||||
|
sizeof(odb->loose_objects_subdir_seen));
|
||||||
|
}
|
||||||
|
|
||||||
r->objects->approximate_object_count_valid = 0;
|
r->objects->approximate_object_count_valid = 0;
|
||||||
r->objects->packed_git_initialized = 0;
|
r->objects->packed_git_initialized = 0;
|
||||||
prepare_packed_git(r);
|
prepare_packed_git(r);
|
||||||
|
2
path.c
2
path.c
@ -385,7 +385,7 @@ static void adjust_git_path(const struct repository *repo,
|
|||||||
strbuf_splice(buf, 0, buf->len,
|
strbuf_splice(buf, 0, buf->len,
|
||||||
repo->index_file, strlen(repo->index_file));
|
repo->index_file, strlen(repo->index_file));
|
||||||
else if (dir_prefix(base, "objects"))
|
else if (dir_prefix(base, "objects"))
|
||||||
replace_dir(buf, git_dir_len + 7, repo->objects->objectdir);
|
replace_dir(buf, git_dir_len + 7, repo->objects->odb->path);
|
||||||
else if (git_hooks_path && dir_prefix(base, "hooks"))
|
else if (git_hooks_path && dir_prefix(base, "hooks"))
|
||||||
replace_dir(buf, git_dir_len + 5, git_hooks_path);
|
replace_dir(buf, git_dir_len + 5, git_hooks_path);
|
||||||
else if (repo->different_commondir)
|
else if (repo->different_commondir)
|
||||||
|
@ -63,8 +63,14 @@ void repo_set_gitdir(struct repository *repo,
|
|||||||
free(old_gitdir);
|
free(old_gitdir);
|
||||||
|
|
||||||
repo_set_commondir(repo, o->commondir);
|
repo_set_commondir(repo, o->commondir);
|
||||||
expand_base_dir(&repo->objects->objectdir, o->object_dir,
|
|
||||||
|
if (!repo->objects->odb) {
|
||||||
|
repo->objects->odb = xcalloc(1, sizeof(*repo->objects->odb));
|
||||||
|
repo->objects->odb_tail = &repo->objects->odb->next;
|
||||||
|
}
|
||||||
|
expand_base_dir(&repo->objects->odb->path, o->object_dir,
|
||||||
repo->commondir, "objects");
|
repo->commondir, "objects");
|
||||||
|
|
||||||
free(repo->objects->alternate_db);
|
free(repo->objects->alternate_db);
|
||||||
repo->objects->alternate_db = xstrdup_or_null(o->alternate_db);
|
repo->objects->alternate_db = xstrdup_or_null(o->alternate_db);
|
||||||
expand_base_dir(&repo->graft_file, o->graft_file,
|
expand_base_dir(&repo->graft_file, o->graft_file,
|
||||||
|
219
sha1-file.c
219
sha1-file.c
@ -346,27 +346,23 @@ static void fill_sha1_path(struct strbuf *buf, const unsigned char *sha1)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sha1_file_name(struct repository *r, struct strbuf *buf, const unsigned char *sha1)
|
static const char *odb_loose_path(struct object_directory *odb,
|
||||||
|
struct strbuf *buf,
|
||||||
|
const unsigned char *sha1)
|
||||||
{
|
{
|
||||||
strbuf_addstr(buf, r->objects->objectdir);
|
strbuf_reset(buf);
|
||||||
|
strbuf_addstr(buf, odb->path);
|
||||||
strbuf_addch(buf, '/');
|
strbuf_addch(buf, '/');
|
||||||
fill_sha1_path(buf, sha1);
|
fill_sha1_path(buf, sha1);
|
||||||
}
|
|
||||||
|
|
||||||
struct strbuf *alt_scratch_buf(struct alternate_object_database *alt)
|
|
||||||
{
|
|
||||||
strbuf_setlen(&alt->scratch, alt->base_len);
|
|
||||||
return &alt->scratch;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *alt_sha1_path(struct alternate_object_database *alt,
|
|
||||||
const unsigned char *sha1)
|
|
||||||
{
|
|
||||||
struct strbuf *buf = alt_scratch_buf(alt);
|
|
||||||
fill_sha1_path(buf, sha1);
|
|
||||||
return buf->buf;
|
return buf->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *loose_object_path(struct repository *r, struct strbuf *buf,
|
||||||
|
const unsigned char *sha1)
|
||||||
|
{
|
||||||
|
return odb_loose_path(r->objects->odb, buf, sha1);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return non-zero iff the path is usable as an alternate object database.
|
* Return non-zero iff the path is usable as an alternate object database.
|
||||||
*/
|
*/
|
||||||
@ -374,7 +370,7 @@ static int alt_odb_usable(struct raw_object_store *o,
|
|||||||
struct strbuf *path,
|
struct strbuf *path,
|
||||||
const char *normalized_objdir)
|
const char *normalized_objdir)
|
||||||
{
|
{
|
||||||
struct alternate_object_database *alt;
|
struct object_directory *odb;
|
||||||
|
|
||||||
/* Detect cases where alternate disappeared */
|
/* Detect cases where alternate disappeared */
|
||||||
if (!is_directory(path->buf)) {
|
if (!is_directory(path->buf)) {
|
||||||
@ -388,8 +384,8 @@ static int alt_odb_usable(struct raw_object_store *o,
|
|||||||
* Prevent the common mistake of listing the same
|
* Prevent the common mistake of listing the same
|
||||||
* thing twice, or object directory itself.
|
* thing twice, or object directory itself.
|
||||||
*/
|
*/
|
||||||
for (alt = o->alt_odb_list; alt; alt = alt->next) {
|
for (odb = o->odb; odb; odb = odb->next) {
|
||||||
if (!fspathcmp(path->buf, alt->path))
|
if (!fspathcmp(path->buf, odb->path))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!fspathcmp(path->buf, normalized_objdir))
|
if (!fspathcmp(path->buf, normalized_objdir))
|
||||||
@ -402,7 +398,7 @@ static int alt_odb_usable(struct raw_object_store *o,
|
|||||||
* Prepare alternate object database registry.
|
* Prepare alternate object database registry.
|
||||||
*
|
*
|
||||||
* The variable alt_odb_list points at the list of struct
|
* The variable alt_odb_list points at the list of struct
|
||||||
* alternate_object_database. The elements on this list come from
|
* object_directory. The elements on this list come from
|
||||||
* non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT
|
* non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT
|
||||||
* environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates,
|
* environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates,
|
||||||
* whose contents is similar to that environment variable but can be
|
* whose contents is similar to that environment variable but can be
|
||||||
@ -419,7 +415,7 @@ static void read_info_alternates(struct repository *r,
|
|||||||
static int link_alt_odb_entry(struct repository *r, const char *entry,
|
static int link_alt_odb_entry(struct repository *r, const char *entry,
|
||||||
const char *relative_base, int depth, const char *normalized_objdir)
|
const char *relative_base, int depth, const char *normalized_objdir)
|
||||||
{
|
{
|
||||||
struct alternate_object_database *ent;
|
struct object_directory *ent;
|
||||||
struct strbuf pathbuf = STRBUF_INIT;
|
struct strbuf pathbuf = STRBUF_INIT;
|
||||||
|
|
||||||
if (!is_absolute_path(entry) && relative_base) {
|
if (!is_absolute_path(entry) && relative_base) {
|
||||||
@ -447,11 +443,12 @@ static int link_alt_odb_entry(struct repository *r, const char *entry,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ent = alloc_alt_odb(pathbuf.buf);
|
ent = xcalloc(1, sizeof(*ent));
|
||||||
|
ent->path = xstrdup(pathbuf.buf);
|
||||||
|
|
||||||
/* add the alternate entry */
|
/* add the alternate entry */
|
||||||
*r->objects->alt_odb_tail = ent;
|
*r->objects->odb_tail = ent;
|
||||||
r->objects->alt_odb_tail = &(ent->next);
|
r->objects->odb_tail = &(ent->next);
|
||||||
ent->next = NULL;
|
ent->next = NULL;
|
||||||
|
|
||||||
/* recursively add alternates */
|
/* recursively add alternates */
|
||||||
@ -505,7 +502,7 @@ static void link_alt_odb_entries(struct repository *r, const char *alt,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
strbuf_add_absolute_path(&objdirbuf, r->objects->objectdir);
|
strbuf_add_absolute_path(&objdirbuf, r->objects->odb->path);
|
||||||
if (strbuf_normalize_path(&objdirbuf) < 0)
|
if (strbuf_normalize_path(&objdirbuf) < 0)
|
||||||
die(_("unable to normalize object directory: %s"),
|
die(_("unable to normalize object directory: %s"),
|
||||||
objdirbuf.buf);
|
objdirbuf.buf);
|
||||||
@ -540,18 +537,6 @@ static void read_info_alternates(struct repository *r,
|
|||||||
free(path);
|
free(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct alternate_object_database *alloc_alt_odb(const char *dir)
|
|
||||||
{
|
|
||||||
struct alternate_object_database *ent;
|
|
||||||
|
|
||||||
FLEX_ALLOC_STR(ent, path, dir);
|
|
||||||
strbuf_init(&ent->scratch, 0);
|
|
||||||
strbuf_addf(&ent->scratch, "%s/", dir);
|
|
||||||
ent->base_len = ent->scratch.len;
|
|
||||||
|
|
||||||
return ent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_to_alternates_file(const char *reference)
|
void add_to_alternates_file(const char *reference)
|
||||||
{
|
{
|
||||||
struct lock_file lock = LOCK_INIT;
|
struct lock_file lock = LOCK_INIT;
|
||||||
@ -588,7 +573,7 @@ void add_to_alternates_file(const char *reference)
|
|||||||
fprintf_or_die(out, "%s\n", reference);
|
fprintf_or_die(out, "%s\n", reference);
|
||||||
if (commit_lock_file(&lock))
|
if (commit_lock_file(&lock))
|
||||||
die_errno(_("unable to move new alternates file into place"));
|
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,
|
link_alt_odb_entries(the_repository, reference,
|
||||||
'\n', NULL, 0);
|
'\n', NULL, 0);
|
||||||
}
|
}
|
||||||
@ -684,11 +669,11 @@ out:
|
|||||||
|
|
||||||
int foreach_alt_odb(alt_odb_fn fn, void *cb)
|
int foreach_alt_odb(alt_odb_fn fn, void *cb)
|
||||||
{
|
{
|
||||||
struct alternate_object_database *ent;
|
struct object_directory *ent;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
prepare_alt_odb(the_repository);
|
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);
|
r = fn(ent, cb);
|
||||||
if (r)
|
if (r)
|
||||||
break;
|
break;
|
||||||
@ -698,13 +683,13 @@ int foreach_alt_odb(alt_odb_fn fn, void *cb)
|
|||||||
|
|
||||||
void prepare_alt_odb(struct repository *r)
|
void prepare_alt_odb(struct repository *r)
|
||||||
{
|
{
|
||||||
if (r->objects->alt_odb_tail)
|
if (r->objects->loaded_alternates)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
r->objects->alt_odb_tail = &r->objects->alt_odb_list;
|
|
||||||
link_alt_odb_entries(r, r->objects->alternate_db, PATH_SEP, NULL, 0);
|
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. */
|
/* Returns 1 if we have successfully freshened the file, 0 otherwise. */
|
||||||
@ -731,23 +716,27 @@ int check_and_freshen_file(const char *fn, int freshen)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_and_freshen_odb(struct object_directory *odb,
|
||||||
|
const struct object_id *oid,
|
||||||
|
int freshen)
|
||||||
|
{
|
||||||
|
static struct strbuf path = STRBUF_INIT;
|
||||||
|
odb_loose_path(odb, &path, oid->hash);
|
||||||
|
return check_and_freshen_file(path.buf, freshen);
|
||||||
|
}
|
||||||
|
|
||||||
static int check_and_freshen_local(const struct object_id *oid, int freshen)
|
static int check_and_freshen_local(const struct object_id *oid, int freshen)
|
||||||
{
|
{
|
||||||
static struct strbuf buf = STRBUF_INIT;
|
return check_and_freshen_odb(the_repository->objects->odb, oid, freshen);
|
||||||
|
|
||||||
strbuf_reset(&buf);
|
|
||||||
sha1_file_name(the_repository, &buf, oid->hash);
|
|
||||||
|
|
||||||
return check_and_freshen_file(buf.buf, freshen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_and_freshen_nonlocal(const struct object_id *oid, int freshen)
|
static int check_and_freshen_nonlocal(const struct object_id *oid, int freshen)
|
||||||
{
|
{
|
||||||
struct alternate_object_database *alt;
|
struct object_directory *odb;
|
||||||
|
|
||||||
prepare_alt_odb(the_repository);
|
prepare_alt_odb(the_repository);
|
||||||
for (alt = the_repository->objects->alt_odb_list; alt; alt = alt->next) {
|
for (odb = the_repository->objects->odb->next; odb; odb = odb->next) {
|
||||||
const char *path = alt_sha1_path(alt, oid->hash);
|
if (check_and_freshen_odb(odb, oid, freshen))
|
||||||
if (check_and_freshen_file(path, freshen))
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -888,25 +877,17 @@ int git_open_cloexec(const char *name, int flags)
|
|||||||
*
|
*
|
||||||
* The "path" out-parameter will give the path of the object we found (if any).
|
* The "path" out-parameter will give the path of the object we found (if any).
|
||||||
* Note that it may point to static storage and is only valid until another
|
* Note that it may point to static storage and is only valid until another
|
||||||
* call to sha1_file_name(), etc.
|
* call to stat_sha1_file().
|
||||||
*/
|
*/
|
||||||
static int stat_sha1_file(struct repository *r, const unsigned char *sha1,
|
static int stat_sha1_file(struct repository *r, const unsigned char *sha1,
|
||||||
struct stat *st, const char **path)
|
struct stat *st, const char **path)
|
||||||
{
|
{
|
||||||
struct alternate_object_database *alt;
|
struct object_directory *odb;
|
||||||
static struct strbuf buf = STRBUF_INIT;
|
static struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
strbuf_reset(&buf);
|
|
||||||
sha1_file_name(r, &buf, sha1);
|
|
||||||
*path = buf.buf;
|
|
||||||
|
|
||||||
if (!lstat(*path, st))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
prepare_alt_odb(r);
|
prepare_alt_odb(r);
|
||||||
errno = ENOENT;
|
for (odb = r->objects->odb; odb; odb = odb->next) {
|
||||||
for (alt = r->objects->alt_odb_list; alt; alt = alt->next) {
|
*path = odb_loose_path(odb, &buf, sha1);
|
||||||
*path = alt_sha1_path(alt, sha1);
|
|
||||||
if (!lstat(*path, st))
|
if (!lstat(*path, st))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -922,25 +903,17 @@ static int open_sha1_file(struct repository *r,
|
|||||||
const unsigned char *sha1, const char **path)
|
const unsigned char *sha1, const char **path)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
struct alternate_object_database *alt;
|
struct object_directory *odb;
|
||||||
int most_interesting_errno;
|
int most_interesting_errno = ENOENT;
|
||||||
static struct strbuf buf = STRBUF_INIT;
|
static struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
strbuf_reset(&buf);
|
|
||||||
sha1_file_name(r, &buf, sha1);
|
|
||||||
*path = buf.buf;
|
|
||||||
|
|
||||||
fd = git_open(*path);
|
|
||||||
if (fd >= 0)
|
|
||||||
return fd;
|
|
||||||
most_interesting_errno = errno;
|
|
||||||
|
|
||||||
prepare_alt_odb(r);
|
prepare_alt_odb(r);
|
||||||
for (alt = r->objects->alt_odb_list; alt; alt = alt->next) {
|
for (odb = r->objects->odb; odb; odb = odb->next) {
|
||||||
*path = alt_sha1_path(alt, sha1);
|
*path = odb_loose_path(odb, &buf, sha1);
|
||||||
fd = git_open(*path);
|
fd = git_open(*path);
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
if (most_interesting_errno == ENOENT)
|
if (most_interesting_errno == ENOENT)
|
||||||
most_interesting_errno = errno;
|
most_interesting_errno = errno;
|
||||||
}
|
}
|
||||||
@ -948,6 +921,24 @@ static int open_sha1_file(struct repository *r,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int quick_has_loose(struct repository *r,
|
||||||
|
const unsigned char *sha1)
|
||||||
|
{
|
||||||
|
int subdir_nr = sha1[0];
|
||||||
|
struct object_id oid;
|
||||||
|
struct object_directory *odb;
|
||||||
|
|
||||||
|
hashcpy(oid.hash, sha1);
|
||||||
|
|
||||||
|
prepare_alt_odb(r);
|
||||||
|
for (odb = r->objects->odb; odb; odb = odb->next) {
|
||||||
|
odb_load_loose_cache(odb, subdir_nr);
|
||||||
|
if (oid_array_lookup(&odb->loose_objects_cache, &oid) >= 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map the loose object at "path" if it is not NULL, or the path found by
|
* Map the loose object at "path" if it is not NULL, or the path found by
|
||||||
* searching for a loose object named "sha1".
|
* searching for a loose object named "sha1".
|
||||||
@ -1198,6 +1189,8 @@ static int sha1_loose_object_info(struct repository *r,
|
|||||||
if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) {
|
if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) {
|
||||||
const char *path;
|
const char *path;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK))
|
||||||
|
return quick_has_loose(r, sha1) ? 0 : -1;
|
||||||
if (stat_sha1_file(r, sha1, &st, &path) < 0)
|
if (stat_sha1_file(r, sha1, &st, &path) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (oi->disk_sizep)
|
if (oi->disk_sizep)
|
||||||
@ -1626,8 +1619,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
|
|||||||
static struct strbuf tmp_file = STRBUF_INIT;
|
static struct strbuf tmp_file = STRBUF_INIT;
|
||||||
static struct strbuf filename = STRBUF_INIT;
|
static struct strbuf filename = STRBUF_INIT;
|
||||||
|
|
||||||
strbuf_reset(&filename);
|
loose_object_path(the_repository, &filename, oid->hash);
|
||||||
sha1_file_name(the_repository, &filename, oid->hash);
|
|
||||||
|
|
||||||
fd = create_tmpfile(&tmp_file, filename.buf);
|
fd = create_tmpfile(&tmp_file, filename.buf);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@ -2134,43 +2126,50 @@ int for_each_loose_file_in_objdir(const char *path,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct loose_alt_odb_data {
|
|
||||||
each_loose_object_fn *cb;
|
|
||||||
void *data;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int loose_from_alt_odb(struct alternate_object_database *alt,
|
|
||||||
void *vdata)
|
|
||||||
{
|
|
||||||
struct loose_alt_odb_data *data = vdata;
|
|
||||||
struct strbuf buf = STRBUF_INIT;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
strbuf_addstr(&buf, alt->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,
|
int for_each_loose_object(each_loose_object_fn cb, void *data,
|
||||||
enum for_each_object_flags flags)
|
enum for_each_object_flags flags)
|
||||||
{
|
{
|
||||||
struct loose_alt_odb_data alt;
|
struct object_directory *odb;
|
||||||
int r;
|
|
||||||
|
|
||||||
r = for_each_loose_file_in_objdir(get_object_directory(),
|
prepare_alt_odb(the_repository);
|
||||||
cb, NULL, NULL, data);
|
for (odb = the_repository->objects->odb; odb; odb = odb->next) {
|
||||||
if (r)
|
int r = for_each_loose_file_in_objdir(odb->path, cb, NULL,
|
||||||
return r;
|
NULL, data);
|
||||||
|
if (r)
|
||||||
|
return r;
|
||||||
|
|
||||||
if (flags & FOR_EACH_OBJECT_LOCAL_ONLY)
|
if (flags & FOR_EACH_OBJECT_LOCAL_ONLY)
|
||||||
return 0;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
alt.cb = cb;
|
return 0;
|
||||||
alt.data = data;
|
}
|
||||||
return foreach_alt_odb(loose_from_alt_odb, &alt);
|
|
||||||
|
static int append_loose_object(const struct object_id *oid, const char *path,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
oid_array_append(data, oid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void odb_load_loose_cache(struct object_directory *odb, int subdir_nr)
|
||||||
|
{
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
|
||||||
|
if (subdir_nr < 0 ||
|
||||||
|
subdir_nr >= ARRAY_SIZE(odb->loose_objects_subdir_seen))
|
||||||
|
BUG("subdir_nr out of range");
|
||||||
|
|
||||||
|
if (odb->loose_objects_subdir_seen[subdir_nr])
|
||||||
|
return;
|
||||||
|
|
||||||
|
strbuf_addstr(&buf, odb->path);
|
||||||
|
for_each_file_in_obj_subdir(subdir_nr, &buf,
|
||||||
|
append_loose_object,
|
||||||
|
NULL, NULL,
|
||||||
|
&odb->loose_objects_cache);
|
||||||
|
odb->loose_objects_subdir_seen[subdir_nr] = 1;
|
||||||
|
strbuf_release(&buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int check_stream_sha1(git_zstream *stream,
|
static int check_stream_sha1(git_zstream *stream,
|
||||||
|
42
sha1-name.c
42
sha1-name.c
@ -83,51 +83,25 @@ static void update_candidates(struct disambiguate_state *ds, const struct object
|
|||||||
/* otherwise, current can be discarded and candidate is still good */
|
/* otherwise, current can be discarded and candidate is still good */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int append_loose_object(const struct object_id *oid, const char *path,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
oid_array_append(data, oid);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int match_sha(unsigned, const unsigned char *, const unsigned char *);
|
static int match_sha(unsigned, const unsigned char *, const unsigned char *);
|
||||||
|
|
||||||
static void find_short_object_filename(struct disambiguate_state *ds)
|
static void find_short_object_filename(struct disambiguate_state *ds)
|
||||||
{
|
{
|
||||||
int subdir_nr = ds->bin_pfx.hash[0];
|
int subdir_nr = ds->bin_pfx.hash[0];
|
||||||
struct alternate_object_database *alt;
|
struct object_directory *odb;
|
||||||
static struct alternate_object_database *fakeent;
|
|
||||||
|
|
||||||
if (!fakeent) {
|
for (odb = the_repository->objects->odb;
|
||||||
/*
|
odb && !ds->ambiguous;
|
||||||
* Create a "fake" alternate object database that
|
odb = odb->next) {
|
||||||
* points to our own object database, to make it
|
|
||||||
* easier to get a temporary working space in
|
|
||||||
* alt->name/alt->base while iterating over the
|
|
||||||
* object databases including our own.
|
|
||||||
*/
|
|
||||||
fakeent = alloc_alt_odb(get_object_directory());
|
|
||||||
}
|
|
||||||
fakeent->next = the_repository->objects->alt_odb_list;
|
|
||||||
|
|
||||||
for (alt = fakeent; alt && !ds->ambiguous; alt = alt->next) {
|
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
if (!alt->loose_objects_subdir_seen[subdir_nr]) {
|
odb_load_loose_cache(odb, subdir_nr);
|
||||||
struct strbuf *buf = alt_scratch_buf(alt);
|
pos = oid_array_lookup(&odb->loose_objects_cache, &ds->bin_pfx);
|
||||||
for_each_file_in_obj_subdir(subdir_nr, buf,
|
|
||||||
append_loose_object,
|
|
||||||
NULL, NULL,
|
|
||||||
&alt->loose_objects_cache);
|
|
||||||
alt->loose_objects_subdir_seen[subdir_nr] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = oid_array_lookup(&alt->loose_objects_cache, &ds->bin_pfx);
|
|
||||||
if (pos < 0)
|
if (pos < 0)
|
||||||
pos = -1 - pos;
|
pos = -1 - pos;
|
||||||
while (!ds->ambiguous && pos < alt->loose_objects_cache.nr) {
|
while (!ds->ambiguous && pos < odb->loose_objects_cache.nr) {
|
||||||
const struct object_id *oid;
|
const struct object_id *oid;
|
||||||
oid = alt->loose_objects_cache.oid + pos;
|
oid = odb->loose_objects_cache.oid + pos;
|
||||||
if (!match_sha(ds->len, ds->bin_pfx.hash, oid->hash))
|
if (!match_sha(ds->len, ds->bin_pfx.hash, oid->hash))
|
||||||
break;
|
break;
|
||||||
update_candidates(ds, oid);
|
update_candidates(ds, oid);
|
||||||
|
@ -1433,7 +1433,7 @@ struct alternate_refs_data {
|
|||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int refs_from_alternate_cb(struct alternate_object_database *e,
|
static int refs_from_alternate_cb(struct object_directory *e,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
struct strbuf path = STRBUF_INIT;
|
struct strbuf path = STRBUF_INIT;
|
||||||
|
Loading…
Reference in New Issue
Block a user