static int fetch_refs_via_pack(struct transport *transport, int nr_heads, struct ref **to_fetch) { int ret = 0; struct git_transport_data *data = transport->data; struct ref *refs; char *dest = xstrdup(transport->url); struct fetch_pack_args args; struct ref *refs_tmp = NULL; memset(&args, 0, sizeof(args)); args.uploadpack = data->options.uploadpack; args.keep_pack = data->options.keep; args.lock_pack = 1; args.use_thin_pack = data->options.thin; args.include_tag = data->options.followtags; args.verbose = (transport->verbose > 1); args.quiet = (transport->verbose < 0); args.no_progress = !transport->progress; args.depth = data->options.depth; args.deepen_since = data->options.deepen_since; args.deepen_not = data->options.deepen_not; args.deepen_relative = data->options.deepen_relative; 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); 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, &data->shallow, &transport->pack_lockfile); close(data->fd[0]); close(data->fd[1]); if (finish_connect(data->conn)) ret = -1; data->conn = NULL; data->got_remote_heads = 0; data->options.self_contained_and_connected = args.self_contained_and_connected; if (refs == NULL) ret = -1; if (report_unmatched_refs(to_fetch, nr_heads)) ret = -1; free_refs(refs_tmp); free_refs(refs); free(dest); return ret; }
static int do_fetch(struct transport *transport, struct refspec *refs, int ref_count) { struct ref *ref_map; struct ref *rm; int autotags = (transport->remote->fetch_tags == 1); if (transport->remote->fetch_tags == 2 && tags != TAGS_UNSET) tags = TAGS_SET; if (transport->remote->fetch_tags == -1) tags = TAGS_UNSET; if (!transport->get_refs_list || !transport->fetch) die("Don't know how to fetch from %s", transport->url); /* if not appending, truncate FETCH_HEAD */ if (!append) { char *filename = git_path("FETCH_HEAD"); FILE *fp = fopen(filename, "w"); if (!fp) return error("cannot open %s: %s\n", filename, strerror(errno)); fclose(fp); } ref_map = get_ref_map(transport, refs, ref_count, tags, &autotags); if (!update_head_ok) check_not_current_branch(ref_map); for (rm = ref_map; rm; rm = rm->next) { if (rm->peer_ref) read_ref(rm->peer_ref->name, rm->peer_ref->old_sha1); } if (tags == TAGS_DEFAULT && autotags) transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1"); if (fetch_refs(transport, ref_map)) { free_refs(ref_map); return 1; } free_refs(ref_map); /* if neither --no-tags nor --tags was specified, do automated tag * following ... */ if (tags == TAGS_DEFAULT && autotags) { struct ref **tail = &ref_map; ref_map = NULL; find_non_local_tags(transport, &ref_map, &tail); if (ref_map) { transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL); transport_set_option(transport, TRANS_OPT_DEPTH, "0"); fetch_refs(transport, ref_map); } free_refs(ref_map); } return 0; }
static void free_discovery(struct discovery *d) { if (d) { if (d == last_discovery) last_discovery = NULL; free(d->buf_alloc); free_refs(d->refs); free(d); } }
static void output_refs(struct ref *refs) { struct ref *posn; for (posn = refs; posn; posn = posn->next) { if (posn->symref) printf("@%s %s\n", posn->symref, posn->name); else printf("%s %s\n", sha1_to_hex(posn->old_sha1), posn->name); } printf("\n"); fflush(stdout); free_refs(refs); }
static void parse_fetch(struct strbuf *buf) { struct ref **to_fetch = NULL; struct ref *list_head = NULL; struct ref **list = &list_head; int alloc_heads = 0, nr_heads = 0; do { if (!prefixcmp(buf->buf, "fetch ")) { char *p = buf->buf + strlen("fetch "); char *name; struct ref *ref; unsigned char old_sha1[20]; if (strlen(p) < 40 || get_sha1_hex(p, old_sha1)) die("protocol error: expected sha/ref, got %s'", p); if (p[40] == ' ') name = p + 41; else if (!p[40]) name = ""; else die("protocol error: expected sha/ref, got %s'", p); ref = alloc_ref(name); hashcpy(ref->old_sha1, old_sha1); *list = ref; list = &ref->next; ALLOC_GROW(to_fetch, nr_heads + 1, alloc_heads); to_fetch[nr_heads++] = ref; } else die("http transport does not support %s", buf->buf); strbuf_reset(buf); if (strbuf_getline(buf, stdin, '\n') == EOF) return; if (!*buf->buf) break; } while (1); if (fetch(nr_heads, to_fetch)) exit(128); /* error already reported */ free_refs(list_head); free(to_fetch); printf("\n"); fflush(stdout); strbuf_reset(buf); }
static void parse_fetch(struct strbuf *buf) { struct ref **to_fetch = NULL; struct ref *list_head = NULL; struct ref **list = &list_head; int alloc_heads = 0, nr_heads = 0; do { const char *p; if (skip_prefix(buf->buf, "fetch ", &p)) { const char *name; struct ref *ref; struct object_id old_oid; if (get_oid_hex(p, &old_oid)) die("protocol error: expected sha/ref, got %s'", p); if (p[GIT_SHA1_HEXSZ] == ' ') name = p + GIT_SHA1_HEXSZ + 1; else if (!p[GIT_SHA1_HEXSZ]) name = ""; else die("protocol error: expected sha/ref, got %s'", p); ref = alloc_ref(name); oidcpy(&ref->old_oid, &old_oid); *list = ref; list = &ref->next; ALLOC_GROW(to_fetch, nr_heads + 1, alloc_heads); to_fetch[nr_heads++] = ref; } else die("http transport does not support %s", buf->buf); strbuf_reset(buf); if (strbuf_getline_lf(buf, stdin) == EOF) return; if (!*buf->buf) break; } while (1); if (fetch(nr_heads, to_fetch)) exit(128); /* error already reported */ free_refs(list_head); free(to_fetch); printf("\n"); fflush(stdout); strbuf_reset(buf); }
static int fetch_refs_via_pack(struct transport *transport, int nr_heads, struct ref **to_fetch) { struct git_transport_data *data = transport->data; char **heads = xmalloc(nr_heads * sizeof(*heads)); char **origh = xmalloc(nr_heads * sizeof(*origh)); const struct ref *refs; char *dest = xstrdup(transport->url); struct fetch_pack_args args; int i; struct ref *refs_tmp = NULL; memset(&args, 0, sizeof(args)); args.uploadpack = data->options.uploadpack; args.keep_pack = data->options.keep; args.lock_pack = 1; args.use_thin_pack = data->options.thin; args.include_tag = data->options.followtags; args.verbose = (transport->verbose > 0); args.quiet = (transport->verbose < 0); args.no_progress = !transport->progress; args.depth = data->options.depth; for (i = 0; i < nr_heads; i++) origh[i] = heads[i] = xstrdup(to_fetch[i]->name); if (!data->got_remote_heads) { connect_setup(transport, 0, 0); get_remote_heads(data->fd[0], &refs_tmp, 0, NULL, 0, NULL); data->got_remote_heads = 1; } refs = fetch_pack(&args, data->fd, data->conn, refs_tmp ? refs_tmp : transport->remote_refs, dest, nr_heads, heads, &transport->pack_lockfile); close(data->fd[0]); close(data->fd[1]); if (finish_connect(data->conn)) refs = NULL; data->conn = NULL; data->got_remote_heads = 0; free_refs(refs_tmp); for (i = 0; i < nr_heads; i++) free(origh[i]); free(origh); free(heads); free(dest); return (refs ? 0 : -1); }
struct ref *fetch_pack(struct fetch_pack_args *args, int fd[], struct child_process *conn, const struct ref *ref, const char *dest, struct ref **sought, int nr_sought, struct oid_array *shallow, char **pack_lockfile, enum protocol_version version) { struct ref *ref_cpy; struct shallow_info si; fetch_pack_setup(); if (nr_sought) nr_sought = remove_duplicates_in_refs(sought, nr_sought); if (!ref) { packet_flush(fd[1]); die(_("no matching remote head")); } prepare_shallow_info(&si, shallow); if (version == protocol_v2) ref_cpy = do_fetch_pack_v2(args, fd, ref, sought, nr_sought, pack_lockfile); else ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, &si, pack_lockfile); reprepare_packed_git(the_repository); if (!args->cloning && args->deepen) { struct check_connected_options opt = CHECK_CONNECTED_INIT; struct ref *iterator = ref_cpy; opt.shallow_file = alternate_shallow_file; if (args->deepen) opt.is_deepening_fetch = 1; if (check_connected(iterate_ref_map, &iterator, &opt)) { error(_("remote did not send all necessary objects")); free_refs(ref_cpy); ref_cpy = NULL; rollback_lock_file(&shallow_lock); goto cleanup; } args->connectivity_checked = 1; } update_shallow(args, sought, nr_sought, &si); cleanup: clear_shallow_info(&si); return ref_cpy; }
static int prune_refs(struct transport *transport, struct ref *ref_map) { int result = 0; struct ref *ref, *stale_refs = get_stale_heads(transport->remote, ref_map); const char *dangling_msg = dry_run ? " (%s will become dangling)\n" : " (%s has become dangling)\n"; for (ref = stale_refs; ref; ref = ref->next) { if (!dry_run) result |= delete_ref(ref->name, NULL, 0); if (verbosity >= 0) { fprintf(stderr, " x %-*s %-*s -> %s\n", TRANSPORT_SUMMARY_WIDTH, "[deleted]", REFCOL_WIDTH, "(none)", prettify_refname(ref->name)); warn_dangling_symref(stderr, dangling_msg, ref->name); } } free_refs(stale_refs); return result; }
static int fetch_refs_via_pack(struct transport *transport, int nr_heads, struct ref **to_fetch) { int ret = 0; struct git_transport_data *data = transport->data; struct ref *refs = NULL; char *dest = xstrdup(transport->url); struct fetch_pack_args args; struct ref *refs_tmp = NULL; memset(&args, 0, sizeof(args)); args.uploadpack = data->options.uploadpack; args.keep_pack = data->options.keep; args.lock_pack = 1; args.use_thin_pack = data->options.thin; args.include_tag = data->options.followtags; args.verbose = (transport->verbose > 1); args.quiet = (transport->verbose < 0); args.no_progress = !transport->progress; args.depth = data->options.depth; args.deepen_since = data->options.deepen_since; args.deepen_not = data->options.deepen_not; args.deepen_relative = data->options.deepen_relative; args.check_self_contained_and_connected = data->options.check_self_contained_and_connected; args.cloning = transport->cloning; args.update_shallow = data->options.update_shallow; args.from_promisor = data->options.from_promisor; args.no_dependents = data->options.no_dependents; args.filter_options = data->options.filter_options; args.stateless_rpc = transport->stateless_rpc; args.server_options = transport->server_options; args.negotiation_tips = data->options.negotiation_tips; if (!data->got_remote_heads) { int i; int must_list_refs = 0; for (i = 0; i < nr_heads; i++) { if (!to_fetch[i]->exact_oid) { must_list_refs = 1; break; } } refs_tmp = handshake(transport, 0, NULL, must_list_refs); } switch (data->version) { case protocol_v2: refs = fetch_pack(&args, data->fd, data->conn, refs_tmp ? refs_tmp : transport->remote_refs, dest, to_fetch, nr_heads, &data->shallow, &transport->pack_lockfile, data->version); break; case protocol_v1: case protocol_v0: refs = fetch_pack(&args, data->fd, data->conn, refs_tmp ? refs_tmp : transport->remote_refs, dest, to_fetch, nr_heads, &data->shallow, &transport->pack_lockfile, data->version); break; case protocol_unknown_version: BUG("unknown protocol version"); } close(data->fd[0]); close(data->fd[1]); if (finish_connect(data->conn)) ret = -1; data->conn = NULL; data->got_remote_heads = 0; data->options.self_contained_and_connected = args.self_contained_and_connected; data->options.connectivity_checked = args.connectivity_checked; if (refs == NULL) ret = -1; if (report_unmatched_refs(to_fetch, nr_heads)) ret = -1; free_refs(refs_tmp); free_refs(refs); free(dest); return ret; }
struct ref *fetch_pack(struct fetch_pack_args *args, int fd[], struct child_process *conn, const struct ref *ref, const char *dest, struct ref **sought, int nr_sought, struct oid_array *shallow, char **pack_lockfile, enum protocol_version version) { struct ref *ref_cpy; struct shallow_info si; fetch_pack_setup(); if (nr_sought) nr_sought = remove_duplicates_in_refs(sought, nr_sought); if (args->no_dependents && !args->filter_options.choice) { /* * The protocol does not support requesting that only the * wanted objects be sent, so approximate this by setting a * "blob:none" filter if no filter is already set. This works * for all object types: note that wanted blobs will still be * sent because they are directly specified as a "want". * * NEEDSWORK: Add an option in the protocol to request that * only the wanted objects be sent, and implement it. */ parse_list_objects_filter(&args->filter_options, "blob:none"); } if (version != protocol_v2 && !ref) { packet_flush(fd[1]); die(_("no matching remote head")); } prepare_shallow_info(&si, shallow); if (version == protocol_v2) ref_cpy = do_fetch_pack_v2(args, fd, ref, sought, nr_sought, pack_lockfile); else ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, &si, pack_lockfile); reprepare_packed_git(the_repository); if (!args->cloning && args->deepen) { struct check_connected_options opt = CHECK_CONNECTED_INIT; struct ref *iterator = ref_cpy; opt.shallow_file = alternate_shallow_file; if (args->deepen) opt.is_deepening_fetch = 1; if (check_connected(iterate_ref_map, &iterator, &opt)) { error(_("remote did not send all necessary objects")); free_refs(ref_cpy); ref_cpy = NULL; rollback_lock_file(&shallow_lock); goto cleanup; } args->connectivity_checked = 1; } update_shallow(args, sought, nr_sought, &si); cleanup: clear_shallow_info(&si); return ref_cpy; }
static int do_fetch(struct transport *transport, struct refspec *refs, int ref_count) { struct string_list existing_refs = { NULL, 0, 0, 0 }; struct string_list_item *peer_item = NULL; struct ref *ref_map; struct ref *rm; int autotags = (transport->remote->fetch_tags == 1); for_each_ref(add_existing, &existing_refs); if (transport->remote->fetch_tags == 2 && tags != TAGS_UNSET) tags = TAGS_SET; if (transport->remote->fetch_tags == -1) tags = TAGS_UNSET; if (!transport->get_refs_list || !transport->fetch) die("Don't know how to fetch from %s", transport->url); /* if not appending, truncate FETCH_HEAD */ if (!append && !dry_run) { int errcode = truncate_fetch_head(); if (errcode) return errcode; } ref_map = get_ref_map(transport, refs, ref_count, tags, &autotags); if (!update_head_ok) check_not_current_branch(ref_map); for (rm = ref_map; rm; rm = rm->next) { if (rm->peer_ref) { peer_item = string_list_lookup(rm->peer_ref->name, &existing_refs); if (peer_item) hashcpy(rm->peer_ref->old_sha1, peer_item->util); } } if (tags == TAGS_DEFAULT && autotags) transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1"); if (fetch_refs(transport, ref_map)) { free_refs(ref_map); return 1; } if (prune) prune_refs(transport, ref_map); free_refs(ref_map); /* if neither --no-tags nor --tags was specified, do automated tag * following ... */ if (tags == TAGS_DEFAULT && autotags) { struct ref **tail = &ref_map; ref_map = NULL; find_non_local_tags(transport, &ref_map, &tail); if (ref_map) { transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL); transport_set_option(transport, TRANS_OPT_DEPTH, "0"); fetch_refs(transport, ref_map); } free_refs(ref_map); } return 0; }