summaryrefslogtreecommitdiff
path: root/sha1-file.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2019-07-19 18:30:21 (GMT)
committerJunio C Hamano <gitster@pobox.com>2019-07-19 18:30:21 (GMT)
commit68e65ded5b790bfd8a1072a7f551a8f283f62f29 (patch)
treecb8013cd29b7766aa63ba5812fd172aefcdbc0d6 /sha1-file.c
parent1eb0a12ec3934b7fc398b118806fdf7550ae636e (diff)
parent39b44ba771a315602fd1fdca2e12dfc31ef9c613 (diff)
downloadgit-68e65ded5b790bfd8a1072a7f551a8f283f62f29.zip
git-68e65ded5b790bfd8a1072a7f551a8f283f62f29.tar.gz
git-68e65ded5b790bfd8a1072a7f551a8f283f62f29.tar.bz2
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.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/sha1-file.c b/sha1-file.c
index 59b2e40..84fd02f 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;