diff options
Diffstat (limited to 'transport.c')
-rw-r--r-- | transport.c | 84 |
1 files changed, 55 insertions, 29 deletions
diff --git a/transport.c b/transport.c index ba5d8afb1b..ca7bb441bf 100644 --- a/transport.c +++ b/transport.c @@ -3,6 +3,8 @@ #include "run-command.h" #include "pkt-line.h" #include "fetch-pack.h" +#include "remote.h" +#include "connect.h" #include "send-pack.h" #include "walker.h" #include "bundle.h" @@ -12,6 +14,7 @@ #include "url.h" #include "submodule.h" #include "string-list.h" +#include "sha1-array.h" /* rsync support */ @@ -167,13 +170,13 @@ static void set_upstreams(struct transport *transport, struct ref *refs, remotename = ref->name; tmp = resolve_ref_unsafe(localname, sha, 1, &flag); if (tmp && flag & REF_ISSYMREF && - !prefixcmp(tmp, "refs/heads/")) + starts_with(tmp, "refs/heads/")) localname = tmp; /* Both source and destination must be local branches. */ - if (!localname || prefixcmp(localname, "refs/heads/")) + if (!localname || !starts_with(localname, "refs/heads/")) continue; - if (!remotename || prefixcmp(remotename, "refs/heads/")) + if (!remotename || !starts_with(remotename, "refs/heads/")) continue; if (!pretend) @@ -189,7 +192,7 @@ static void set_upstreams(struct transport *transport, struct ref *refs, static const char *rsync_url(const char *url) { - return prefixcmp(url, "rsync://") ? skip_prefix(url, "rsync:") : url; + return !starts_with(url, "rsync://") ? skip_prefix(url, "rsync:") : url; } static struct ref *get_refs_via_rsync(struct transport *transport, int for_push) @@ -294,8 +297,8 @@ static int write_one_ref(const char *name, const unsigned char *sha1, FILE *f; /* when called via for_each_ref(), flags is non-zero */ - if (flags && prefixcmp(name, "refs/heads/") && - prefixcmp(name, "refs/tags/")) + if (flags && !starts_with(name, "refs/heads/") && + !starts_with(name, "refs/tags/")) return 0; strbuf_addstr(buf, name); @@ -452,7 +455,8 @@ struct git_transport_data { struct child_process *conn; int fd[2]; unsigned got_remote_heads : 1; - struct extra_have_objects extra_have; + struct sha1_array extra_have; + struct sha1_array shallow; }; static int set_git_option(struct git_transport_options *opts, @@ -473,6 +477,9 @@ static int set_git_option(struct git_transport_options *opts, } else if (!strcmp(name, TRANS_OPT_KEEP)) { opts->keep = !!value; return 0; + } else if (!strcmp(name, TRANS_OPT_UPDATE_SHALLOW)) { + opts->update_shallow = !!value; + return 0; } else if (!strcmp(name, TRANS_OPT_DEPTH)) { if (!value) opts->depth = 0; @@ -509,7 +516,9 @@ static struct ref *get_refs_via_connect(struct transport *transport, int for_pus connect_setup(transport, for_push, 0); get_remote_heads(data->fd[0], NULL, 0, &refs, - for_push ? REF_NORMAL : 0, &data->extra_have); + for_push ? REF_NORMAL : 0, + &data->extra_have, + &data->shallow); data->got_remote_heads = 1; return refs; @@ -534,16 +543,21 @@ static int fetch_refs_via_pack(struct transport *transport, args.quiet = (transport->verbose < 0); args.no_progress = !transport->progress; args.depth = data->options.depth; + args.check_self_contained_and_connected = + data->options.check_self_contained_and_connected; + args.cloning = transport->cloning; + args.update_shallow = data->options.update_shallow; if (!data->got_remote_heads) { connect_setup(transport, 0, 0); - get_remote_heads(data->fd[0], NULL, 0, &refs_tmp, 0, NULL); + get_remote_heads(data->fd[0], NULL, 0, &refs_tmp, 0, + NULL, &data->shallow); data->got_remote_heads = 1; } refs = fetch_pack(&args, data->fd, data->conn, refs_tmp ? refs_tmp : transport->remote_refs, - dest, to_fetch, nr_heads, + dest, to_fetch, nr_heads, &data->shallow, &transport->pack_lockfile); close(data->fd[0]); close(data->fd[1]); @@ -551,6 +565,8 @@ static int fetch_refs_via_pack(struct transport *transport, refs = NULL; data->conn = NULL; data->got_remote_heads = 0; + data->options.self_contained_and_connected = + args.self_contained_and_connected; free_refs(refs_tmp); @@ -646,7 +662,7 @@ static void print_ok_ref_status(struct ref *ref, int porcelain) print_ref_status('-', "[deleted]", ref, NULL, NULL, porcelain); else if (is_null_sha1(ref->old_sha1)) print_ref_status('*', - (!prefixcmp(ref->name, "refs/tags/") ? "[new tag]" : + (starts_with(ref->name, "refs/tags/") ? "[new tag]" : "[new branch]"), ref, ref->peer_ref, NULL, porcelain); else { @@ -703,6 +719,14 @@ static int print_one_push_status(struct ref *ref, const char *dest, int count, i print_ref_status('!', "[rejected]", ref, ref->peer_ref, "needs force", porcelain); break; + case REF_STATUS_REJECT_STALE: + print_ref_status('!', "[rejected]", ref, ref->peer_ref, + "stale info", porcelain); + break; + case REF_STATUS_REJECT_SHALLOW: + print_ref_status('!', "[rejected]", ref, ref->peer_ref, + "new shallow roots not allowed", porcelain); + break; case REF_STATUS_REMOTE_REJECT: print_ref_status('!', "[remote rejected]", ref, ref->deletion ? NULL : ref->peer_ref, @@ -795,7 +819,8 @@ static int git_transport_push(struct transport *transport, struct ref *remote_re struct ref *tmp_refs; connect_setup(transport, 1, 0); - get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL, NULL); + get_remote_heads(data->fd[0], NULL, 0, &tmp_refs, REF_NORMAL, + NULL, &data->shallow); data->got_remote_heads = 1; } @@ -871,14 +896,8 @@ void transport_take_over(struct transport *transport, transport->push_refs = git_transport_push; transport->disconnect = disconnect_git; transport->smart_options = &(data->options); -} -static int is_local(const char *url) -{ - const char *colon = strchr(url, ':'); - const char *slash = strchr(url, '/'); - return !colon || (slash && slash < colon) || - has_dos_drive_prefix(url); + transport->cannot_reuse = 1; } static int is_file(const char *url) @@ -918,18 +937,18 @@ struct transport *transport_get(struct remote *remote, const char *url) while (is_urlschemechar(p == url, *p)) p++; - if (!prefixcmp(p, "::")) + if (starts_with(p, "::")) helper = xstrndup(url, p - url); } if (helper) { transport_helper_init(ret, helper); - } else if (!prefixcmp(url, "rsync:")) { + } else if (starts_with(url, "rsync:")) { ret->get_refs_list = get_refs_via_rsync; ret->fetch = fetch_objs_via_rsync; ret->push = rsync_transport_push; ret->smart_options = NULL; - } else if (is_local(url) && is_file(url) && is_bundle(url, 1)) { + } else if (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) { struct bundle_transport_data *data = xcalloc(1, sizeof(*data)); ret->data = data; ret->get_refs_list = get_refs_from_bundle; @@ -937,11 +956,11 @@ struct transport *transport_get(struct remote *remote, const char *url) ret->disconnect = close_bundle; ret->smart_options = NULL; } else if (!is_url(url) - || !prefixcmp(url, "file://") - || !prefixcmp(url, "git://") - || !prefixcmp(url, "ssh://") - || !prefixcmp(url, "git+ssh://") - || !prefixcmp(url, "ssh+git://")) { + || starts_with(url, "file://") + || starts_with(url, "git://") + || starts_with(url, "ssh://") + || starts_with(url, "git+ssh://") + || starts_with(url, "ssh+git://")) { /* These are builtin smart transports. */ struct git_transport_data *data = xcalloc(1, sizeof(*data)); ret->data = data; @@ -1072,6 +1091,7 @@ static int run_pre_push_hook(struct transport *transport, for (r = remote_refs; r; r = r->next) { if (!r->peer_ref) continue; if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue; + if (r->status == REF_STATUS_REJECT_STALE) continue; if (r->status == REF_STATUS_UPTODATE) continue; strbuf_reset(&buf); @@ -1136,6 +1156,12 @@ int transport_push(struct transport *transport, return -1; } + if (transport->smart_options && + transport->smart_options->cas && + !is_empty_cas(transport->smart_options->cas)) + apply_push_cas(transport->smart_options->cas, + transport->remote, remote_refs); + set_ref_status_for_push(remote_refs, flags & TRANSPORT_PUSH_MIRROR, flags & TRANSPORT_PUSH_FORCE); @@ -1228,7 +1254,7 @@ int transport_fetch_refs(struct transport *transport, struct ref *refs) * then local and remote refs are likely to still be equal. * Just feed them all to the fetch method in that case. * This condition shouldn't be met in a non-deepening fetch - * (see builtin-fetch.c:quickfetch()). + * (see builtin/fetch.c:quickfetch()). */ heads = xmalloc(nr_refs * sizeof(*heads)); for (rm = refs; rm; rm = rm->next) @@ -1278,7 +1304,7 @@ char *transport_anonymize_url(const char *url) size_t anon_len, prefix_len = 0; anon_part = strchr(url, '@'); - if (is_local(url) || !anon_part) + if (url_is_local_not_ssh(url) || !anon_part) goto literal_copy; anon_len = strlen(++anon_part); |