diff options
Diffstat (limited to 'transport-helper.c')
-rw-r--r-- | transport-helper.c | 95 |
1 files changed, 70 insertions, 25 deletions
diff --git a/transport-helper.c b/transport-helper.c index 413d9d873e..defafbf4c1 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -9,7 +9,7 @@ #include "string-list.h" #include "thread-utils.h" #include "sigchain.h" -#include "argv-array.h" +#include "strvec.h" #include "refs.h" #include "refspec.h" #include "transport-internal.h" @@ -32,7 +32,8 @@ struct helper_data { signed_tags : 1, check_connectivity : 1, no_disconnect_req : 1, - no_private_update : 1; + no_private_update : 1, + object_format : 1; /* * As an optimization, the transport code may invoke fetch before @@ -127,17 +128,17 @@ static struct child_process *get_helper(struct transport *transport) helper->in = -1; helper->out = -1; helper->err = 0; - argv_array_pushf(&helper->args, "git-remote-%s", data->name); - argv_array_push(&helper->args, transport->remote->name); - argv_array_push(&helper->args, remove_ext_force(transport->url)); + strvec_pushf(&helper->args, "git-remote-%s", data->name); + strvec_push(&helper->args, transport->remote->name); + strvec_push(&helper->args, remove_ext_force(transport->url)); helper->git_cmd = 0; helper->silent_exec_failure = 1; if (have_git_dir()) - argv_array_pushf(&helper->env_array, "%s=%s", - GIT_DIR_ENVIRONMENT, get_git_dir()); + strvec_pushf(&helper->env_array, "%s=%s", + GIT_DIR_ENVIRONMENT, get_git_dir()); - helper->trace2_child_class = helper->args.argv[0]; /* "remote-<name>" */ + helper->trace2_child_class = helper->args.v[0]; /* "remote-<name>" */ code = start_command(helper); if (code < 0 && errno == ENOENT) @@ -207,6 +208,8 @@ static struct child_process *get_helper(struct transport *transport) data->import_marks = xstrdup(arg); } else if (starts_with(capname, "no-private-update")) { data->no_private_update = 1; + } else if (starts_with(capname, "object-format")) { + data->object_format = 1; } else if (mandatory) { die(_("unknown mandatory capability %s; this remote " "helper probably needs newer version of Git"), @@ -404,15 +407,17 @@ static int fetch_with_fetch(struct transport *transport, sendline(data, &buf); while (1) { + const char *name; + if (recvline(data, &buf)) exit(128); - if (starts_with(buf.buf, "lock ")) { - const char *name = buf.buf + 5; - if (transport->pack_lockfile) + if (skip_prefix(buf.buf, "lock ", &name)) { + if (transport->pack_lockfiles.nr) warning(_("%s also locked %s"), data->name, name); else - transport->pack_lockfile = xstrdup(name); + string_list_append(&transport->pack_lockfiles, + name); } else if (data->check_connectivity && data->transport_options.check_self_contained_and_connected && @@ -434,13 +439,13 @@ static int get_importer(struct transport *transport, struct child_process *fasti int cat_blob_fd, code; child_process_init(fastimport); fastimport->in = xdup(helper->out); - argv_array_push(&fastimport->args, "fast-import"); - argv_array_push(&fastimport->args, "--allow-unsafe-features"); - argv_array_push(&fastimport->args, debug ? "--stats" : "--quiet"); + strvec_push(&fastimport->args, "fast-import"); + strvec_push(&fastimport->args, "--allow-unsafe-features"); + strvec_push(&fastimport->args, debug ? "--stats" : "--quiet"); if (data->bidi_import) { cat_blob_fd = xdup(helper->in); - argv_array_pushf(&fastimport->args, "--cat-blob-fd=%d", cat_blob_fd); + strvec_pushf(&fastimport->args, "--cat-blob-fd=%d", cat_blob_fd); } fastimport->git_cmd = 1; @@ -461,17 +466,17 @@ static int get_exporter(struct transport *transport, /* we need to duplicate helper->in because we want to use it after * fastexport is done with it. */ fastexport->out = dup(helper->in); - argv_array_push(&fastexport->args, "fast-export"); - argv_array_push(&fastexport->args, "--use-done-feature"); - argv_array_push(&fastexport->args, data->signed_tags ? + strvec_push(&fastexport->args, "fast-export"); + strvec_push(&fastexport->args, "--use-done-feature"); + strvec_push(&fastexport->args, data->signed_tags ? "--signed-tags=verbatim" : "--signed-tags=warn-strip"); if (data->export_marks) - argv_array_pushf(&fastexport->args, "--export-marks=%s.tmp", data->export_marks); + strvec_pushf(&fastexport->args, "--export-marks=%s.tmp", data->export_marks); if (data->import_marks) - argv_array_pushf(&fastexport->args, "--import-marks=%s", data->import_marks); + strvec_pushf(&fastexport->args, "--import-marks=%s", data->import_marks); for (i = 0; i < revlist_args->nr; i++) - argv_array_push(&fastexport->args, revlist_args->items[i].string); + strvec_push(&fastexport->args, revlist_args->items[i].string); fastexport->git_cmd = 1; return start_command(fastexport); @@ -893,6 +898,7 @@ static int push_refs_with_push(struct transport *transport, case REF_STATUS_REJECT_STALE: case REF_STATUS_REJECT_ALREADY_EXISTS: if (atomic) { + reject_atomic_push(remote_refs, mirror); string_list_clear(&cas_options, 0); return 0; } else @@ -1044,7 +1050,7 @@ static int push_refs(struct transport *transport, if (!remote_refs) { fprintf(stderr, _("No refs in common and none specified; doing nothing.\n" - "Perhaps you should specify a branch such as 'master'.\n")); + "Perhaps you should specify a branch.\n")); return 0; } @@ -1076,7 +1082,7 @@ static int has_attribute(const char *attrs, const char *attr) } static struct ref *get_refs_list(struct transport *transport, int for_push, - const struct argv_array *ref_prefixes) + const struct strvec *ref_prefixes) { get_helper(transport); @@ -1101,6 +1107,12 @@ static struct ref *get_refs_list_using_list(struct transport *transport, data->get_refs_list_called = 1; helper = get_helper(transport); + if (data->object_format) { + write_str_in_full(helper->in, "option object-format\n"); + if (recvline(data, &buf) || strcmp(buf.buf, "ok")) + exit(128); + } + if (data->push && for_push) write_str_in_full(helper->in, "list for-push\n"); else @@ -1113,6 +1125,17 @@ static struct ref *get_refs_list_using_list(struct transport *transport, if (!*buf.buf) break; + else if (buf.buf[0] == ':') { + const char *value; + if (skip_prefix(buf.buf, ":object-format ", &value)) { + int algo = hash_algo_by_name(value); + if (algo == GIT_HASH_UNKNOWN) + die(_("unsupported object format '%s'"), + value); + transport->hash_algo = &hash_algos[algo]; + } + continue; + } eov = strchr(buf.buf, ' '); if (!eov) @@ -1125,7 +1148,7 @@ static struct ref *get_refs_list_using_list(struct transport *transport, if (buf.buf[0] == '@') (*tail)->symref = xstrdup(buf.buf + 1); else if (buf.buf[0] != '?') - get_oid_hex(buf.buf, &(*tail)->old_oid); + get_oid_hex_algop(buf.buf, &(*tail)->old_oid, transport->hash_algo); if (eon) { if (has_attribute(eon + 1, "unchanged")) { (*tail)->status |= REF_STATUS_UPTODATE; @@ -1487,3 +1510,25 @@ int bidirectional_transfer_loop(int input, int output) return tloop_spawnwait_tasks(&state); } + +void reject_atomic_push(struct ref *remote_refs, int mirror_mode) +{ + struct ref *ref; + + /* Mark other refs as failed */ + for (ref = remote_refs; ref; ref = ref->next) { + if (!ref->peer_ref && !mirror_mode) + continue; + + switch (ref->status) { + case REF_STATUS_NONE: + case REF_STATUS_OK: + case REF_STATUS_EXPECTING_REPORT: + ref->status = REF_STATUS_ATOMIC_PUSH_FAILED; + continue; + default: + break; /* do nothing */ + } + } + return; +} |