diff options
author | Junio C Hamano <gitster@pobox.com> | 2019-07-19 11:30:21 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2019-07-19 11:30:21 -0700 |
commit | 68e65ded5b790bfd8a1072a7f551a8f283f62f29 (patch) | |
tree | cb8013cd29b7766aa63ba5812fd172aefcdbc0d6 /sha1-file.c | |
parent | 1eb0a12ec3934b7fc398b118806fdf7550ae636e (diff) | |
parent | 39b44ba771a315602fd1fdca2e12dfc31ef9c613 (diff) | |
download | git-68e65ded5b790bfd8a1072a7f551a8f283f62f29.tar.gz |
Merge branch 'jk/check-connected-with-alternates'
The tips of refs from the alternate object store can be used as
starting point for reachability computation now.
* jk/check-connected-with-alternates:
check_everything_connected: assume alternate ref tips are valid
object-store.h: move for_each_alternate_ref() from transport.h
Diffstat (limited to 'sha1-file.c')
-rw-r--r-- | sha1-file.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/sha1-file.c b/sha1-file.c index 59b2e40cf3..84fd02f107 100644 --- a/sha1-file.c +++ b/sha1-file.c @@ -743,6 +743,103 @@ 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); +} + +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; |