diff options
Diffstat (limited to 'sha1-file.c')
-rw-r--r-- | sha1-file.c | 114 |
1 files changed, 111 insertions, 3 deletions
diff --git a/sha1-file.c b/sha1-file.c index 494606f771..487ea35d2d 100644 --- a/sha1-file.c +++ b/sha1-file.c @@ -189,6 +189,14 @@ int hash_algo_by_id(uint32_t format_id) return GIT_HASH_UNKNOWN; } +int hash_algo_by_length(int len) +{ + int i; + for (i = 1; i < GIT_HASH_NALGOS; i++) + if (len == hash_algos[i].rawsz) + return i; + return GIT_HASH_UNKNOWN; +} /* * This is meant to hold a *small* number of objects that you would @@ -735,6 +743,104 @@ out: return ref_git; } +static void fill_alternate_refs_command(struct child_process *cmd, + const char *repo_path) +{ + const char *value; + + if (!git_config_get_value("core.alternateRefsCommand", &value)) { + cmd->use_shell = 1; + + argv_array_push(&cmd->args, value); + argv_array_push(&cmd->args, repo_path); + } else { + cmd->git_cmd = 1; + + argv_array_pushf(&cmd->args, "--git-dir=%s", repo_path); + argv_array_push(&cmd->args, "for-each-ref"); + argv_array_push(&cmd->args, "--format=%(objectname)"); + + if (!git_config_get_value("core.alternateRefsPrefixes", &value)) { + argv_array_push(&cmd->args, "--"); + argv_array_split(&cmd->args, value); + } + } + + cmd->env = local_repo_env; + cmd->out = -1; +} + +static void read_alternate_refs(const char *path, + alternate_ref_fn *cb, + void *data) +{ + struct child_process cmd = CHILD_PROCESS_INIT; + struct strbuf line = STRBUF_INIT; + FILE *fh; + + fill_alternate_refs_command(&cmd, path); + + if (start_command(&cmd)) + return; + + fh = xfdopen(cmd.out, "r"); + while (strbuf_getline_lf(&line, fh) != EOF) { + struct object_id oid; + const char *p; + + if (parse_oid_hex(line.buf, &oid, &p) || *p) { + warning(_("invalid line while parsing alternate refs: %s"), + line.buf); + break; + } + + cb(&oid, data); + } + + fclose(fh); + finish_command(&cmd); + strbuf_release(&line); +} + +struct alternate_refs_data { + alternate_ref_fn *fn; + void *data; +}; + +static int refs_from_alternate_cb(struct object_directory *e, + void *data) +{ + struct strbuf path = STRBUF_INIT; + size_t base_len; + struct alternate_refs_data *cb = data; + + if (!strbuf_realpath(&path, e->path, 0)) + goto out; + if (!strbuf_strip_suffix(&path, "/objects")) + goto out; + base_len = path.len; + + /* Is this a git repository with refs? */ + strbuf_addstr(&path, "/refs"); + if (!is_directory(path.buf)) + goto out; + strbuf_setlen(&path, base_len); + + read_alternate_refs(path.buf, cb->fn, cb->data); + +out: + strbuf_release(&path); + return 0; +} + +void for_each_alternate_ref(alternate_ref_fn fn, void *data) +{ + struct alternate_refs_data cb; + cb.fn = fn; + cb.data = data; + foreach_alt_odb(refs_from_alternate_cb, &cb); +} + int foreach_alt_odb(alt_odb_fn fn, void *cb) { struct object_directory *ent; @@ -1370,7 +1476,8 @@ int oid_object_info_extended(struct repository *r, const struct object_id *oid, /* Check if it is a missing object */ if (fetch_if_missing && repository_format_partial_clone && - !already_retried && r == the_repository) { + !already_retried && r == the_repository && + !(flags & OBJECT_INFO_SKIP_FETCH_OBJECT)) { /* * TODO Investigate having fetch_object() return * TODO error/success and stopping the music here. @@ -1496,7 +1603,8 @@ void *read_object_file_extended(struct repository *r, return NULL; } -void *read_object_with_reference(const struct object_id *oid, +void *read_object_with_reference(struct repository *r, + const struct object_id *oid, const char *required_type_name, unsigned long *size, struct object_id *actual_oid_return) @@ -1512,7 +1620,7 @@ void *read_object_with_reference(const struct object_id *oid, int ref_length = -1; const char *ref_type = NULL; - buffer = read_object_file(&actual_oid, &type, &isize); + buffer = repo_read_object_file(r, &actual_oid, &type, &isize); if (!buffer) return NULL; if (type == required_type) { |