static int list_tags(struct ref_filter *filter, struct ref_sorting *sorting, const char *format) { struct ref_array array; char *to_free = NULL; int i; memset(&array, 0, sizeof(array)); if (filter->lines == -1) filter->lines = 0; if (!format) { if (filter->lines) { to_free = xstrfmt("%s %%(contents:lines=%d)", "%(align:15)%(refname:strip=2)%(end)", filter->lines); format = to_free; } else format = "%(refname:strip=2)"; } verify_ref_format(format); filter->with_commit_tag_algo = 1; filter_refs(&array, filter, FILTER_REFS_TAGS); ref_array_sort(sorting, &array); for (i = 0; i < array.nr; i++) show_ref_array_item(array.items[i], format, 0); ref_array_clear(&array); free(to_free); return 0; }
static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting, struct ref_format *format) { int i; struct ref_array array; int maxwidth = 0; const char *remote_prefix = ""; char *to_free = NULL; /* * If we are listing more than just remote branches, * then remote branches will have a "remotes/" prefix. * We need to account for this in the width. */ if (filter->kind != FILTER_REFS_REMOTES) remote_prefix = "remotes/"; memset(&array, 0, sizeof(array)); filter_refs(&array, filter, filter->kind | FILTER_REFS_INCLUDE_BROKEN); if (filter->verbose) maxwidth = calc_maxwidth(&array, strlen(remote_prefix)); if (!format->format) format->format = to_free = build_format(filter, maxwidth, remote_prefix); format->use_color = branch_use_color; if (verify_ref_format(format)) die(_("unable to parse format string")); ref_array_sort(sorting, &array); for (i = 0; i < array.nr; i++) { struct strbuf out = STRBUF_INIT; struct strbuf err = STRBUF_INIT; if (format_ref_array_item(array.items[i], format, &out, &err)) die("%s", err.buf); if (column_active(colopts)) { assert(!filter->verbose && "--column and --verbose are incompatible"); /* format to a string_list to let print_columns() do its job */ string_list_append(&output, out.buf); } else { fwrite(out.buf, 1, out.len, stdout); putchar('\n'); } strbuf_release(&err); strbuf_release(&out); } ref_array_clear(&array); free(to_free); }
static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sorting) { int i; struct ref_array array; int maxwidth = 0; const char *remote_prefix = ""; /* * If we are listing more than just remote branches, * then remote branches will have a "remotes/" prefix. * We need to account for this in the width. */ if (filter->kind != FILTER_REFS_REMOTES) remote_prefix = "remotes/"; memset(&array, 0, sizeof(array)); verify_ref_format("%(refname)%(symref)"); filter_refs(&array, filter, filter->kind | FILTER_REFS_INCLUDE_BROKEN); if (filter->verbose) maxwidth = calc_maxwidth(&array, strlen(remote_prefix)); /* * If no sorting parameter is given then we default to sorting * by 'refname'. This would give us an alphabetically sorted * array with the 'HEAD' ref at the beginning followed by * local branches 'refs/heads/...' and finally remote-tacking * branches 'refs/remotes/...'. */ if (!sorting) sorting = ref_default_sorting(); ref_array_sort(sorting, &array); for (i = 0; i < array.nr; i++) format_and_print_ref_item(array.items[i], maxwidth, filter, remote_prefix); ref_array_clear(&array); }
static int everything_local(struct fetch_pack_args *args, struct ref **refs, struct ref **sought, int nr_sought) { struct ref *ref; int retval; unsigned long cutoff = 0; save_commit_buffer = 0; for (ref = *refs; ref; ref = ref->next) { struct object *o; if (!has_sha1_file(ref->old_sha1)) continue; o = parse_object(ref->old_sha1); if (!o) continue; /* We already have it -- which may mean that we were * in sync with the other side at some time after * that (it is OK if we guess wrong here). */ if (o->type == OBJ_COMMIT) { struct commit *commit = (struct commit *)o; if (!cutoff || cutoff < commit->date) cutoff = commit->date; } } if (!args->depth) { for_each_ref(mark_complete, NULL); for_each_alternate_ref(mark_alternate_complete, NULL); commit_list_sort_by_date(&complete); if (cutoff) mark_recent_complete_commits(args, cutoff); } /* * Mark all complete remote refs as common refs. * Don't mark them common yet; the server has to be told so first. */ for (ref = *refs; ref; ref = ref->next) { struct object *o = deref_tag(lookup_object(ref->old_sha1), NULL, 0); if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE)) continue; if (!(o->flags & SEEN)) { rev_list_push((struct commit *)o, COMMON_REF | SEEN); mark_common((struct commit *)o, 1, 1); } } filter_refs(args, refs, sought, nr_sought); for (retval = 1, ref = *refs; ref ; ref = ref->next) { const unsigned char *remote = ref->old_sha1; unsigned char local[20]; struct object *o; o = lookup_object(remote); if (!o || !(o->flags & COMPLETE)) { retval = 0; if (!args->verbose) continue; fprintf(stderr, "want %s (%s)\n", sha1_to_hex(remote), ref->name); continue; } hashcpy(ref->new_sha1, local); if (!args->verbose) continue; fprintf(stderr, "already have %s (%s)\n", sha1_to_hex(remote), ref->name); } return retval; }
int cmd_for_each_ref(int argc, const char **argv, const char *prefix) { int i; const char *format = "%(objectname) %(objecttype)\t%(refname)"; struct ref_sorting *sorting = NULL, **sorting_tail = &sorting; int maxcount = 0, quote_style = 0; struct ref_array array; struct ref_filter filter; struct option opts[] = { OPT_BIT('s', "shell", "e_style, N_("quote placeholders suitably for shells"), QUOTE_SHELL), OPT_BIT('p', "perl", "e_style, N_("quote placeholders suitably for perl"), QUOTE_PERL), OPT_BIT(0 , "python", "e_style, N_("quote placeholders suitably for python"), QUOTE_PYTHON), OPT_BIT(0 , "tcl", "e_style, N_("quote placeholders suitably for Tcl"), QUOTE_TCL), OPT_GROUP(""), OPT_INTEGER( 0 , "count", &maxcount, N_("show only <n> matched refs")), OPT_STRING( 0 , "format", &format, N_("format"), N_("format to use for the output")), OPT_CALLBACK(0 , "sort", sorting_tail, N_("key"), N_("field name to sort on"), &parse_opt_ref_sorting), OPT_CALLBACK(0, "points-at", &filter.points_at, N_("object"), N_("print only refs which points at the given object"), parse_opt_object_name), OPT_MERGED(&filter, N_("print only refs that are merged")), OPT_NO_MERGED(&filter, N_("print only refs that are not merged")), OPT_CONTAINS(&filter.with_commit, N_("print only refs which contain the commit")), OPT_END(), }; memset(&array, 0, sizeof(array)); memset(&filter, 0, sizeof(filter)); parse_options(argc, argv, prefix, opts, for_each_ref_usage, 0); if (maxcount < 0) { error("invalid --count argument: `%d'", maxcount); usage_with_options(for_each_ref_usage, opts); } if (HAS_MULTI_BITS(quote_style)) { error("more than one quoting style?"); usage_with_options(for_each_ref_usage, opts); } if (verify_ref_format(format)) usage_with_options(for_each_ref_usage, opts); if (!sorting) sorting = ref_default_sorting(); /* for warn_ambiguous_refs */ git_config(git_default_config, NULL); filter.name_patterns = argv; filter.match_as_path = 1; filter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN); ref_array_sort(sorting, &array); if (!maxcount || array.nr < maxcount) maxcount = array.nr; for (i = 0; i < maxcount; i++) show_ref_array_item(array.items[i], format, quote_style); ref_array_clear(&array); return 0; }
static struct ref *do_fetch_pack(struct fetch_pack_args *args, int fd[2], const struct ref *orig_ref, struct ref **sought, int nr_sought, struct shallow_info *si, char **pack_lockfile) { struct ref *ref = copy_ref_list(orig_ref); struct object_id oid; const char *agent_feature; int agent_len; struct fetch_negotiator negotiator; fetch_negotiator_init(&negotiator, negotiation_algorithm); sort_ref_list(&ref, ref_compare_name); QSORT(sought, nr_sought, cmp_ref_by_name); if ((args->depth > 0 || is_repository_shallow(the_repository)) && !server_supports("shallow")) die(_("Server does not support shallow clients")); if (args->depth > 0 || args->deepen_since || args->deepen_not) args->deepen = 1; if (server_supports("multi_ack_detailed")) { print_verbose(args, _("Server supports multi_ack_detailed")); multi_ack = 2; if (server_supports("no-done")) { print_verbose(args, _("Server supports no-done")); if (args->stateless_rpc) no_done = 1; } } else if (server_supports("multi_ack")) { print_verbose(args, _("Server supports multi_ack")); multi_ack = 1; } if (server_supports("side-band-64k")) { print_verbose(args, _("Server supports side-band-64k")); use_sideband = 2; } else if (server_supports("side-band")) { print_verbose(args, _("Server supports side-band")); use_sideband = 1; } if (server_supports("allow-tip-sha1-in-want")) { print_verbose(args, _("Server supports allow-tip-sha1-in-want")); allow_unadvertised_object_request |= ALLOW_TIP_SHA1; } if (server_supports("allow-reachable-sha1-in-want")) { print_verbose(args, _("Server supports allow-reachable-sha1-in-want")); allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1; } if (!server_supports("thin-pack")) args->use_thin_pack = 0; if (!server_supports("no-progress")) args->no_progress = 0; if (!server_supports("include-tag")) args->include_tag = 0; if (server_supports("ofs-delta")) print_verbose(args, _("Server supports ofs-delta")); else prefer_ofs_delta = 0; if (server_supports("filter")) { server_supports_filtering = 1; print_verbose(args, _("Server supports filter")); } else if (args->filter_options.choice) { warning("filtering not recognized by server, ignoring"); } if ((agent_feature = server_feature_value("agent", &agent_len))) { agent_supported = 1; if (agent_len) print_verbose(args, _("Server version is %.*s"), agent_len, agent_feature); } if (server_supports("deepen-since")) deepen_since_ok = 1; else if (args->deepen_since) die(_("Server does not support --shallow-since")); if (server_supports("deepen-not")) deepen_not_ok = 1; else if (args->deepen_not) die(_("Server does not support --shallow-exclude")); if (!server_supports("deepen-relative") && args->deepen_relative) die(_("Server does not support --deepen")); if (!args->no_dependents) { mark_complete_and_common_ref(&negotiator, args, &ref); filter_refs(args, &ref, sought, nr_sought); if (everything_local(args, &ref)) { packet_flush(fd[1]); goto all_done; } } else { filter_refs(args, &ref, sought, nr_sought); } if (find_common(&negotiator, args, fd, &oid, ref) < 0) if (!args->keep_pack) /* When cloning, it is not unusual to have * no common commit. */ warning(_("no common commits")); if (args->stateless_rpc) packet_flush(fd[1]); if (args->deepen) setup_alternate_shallow(&shallow_lock, &alternate_shallow_file, NULL); else if (si->nr_ours || si->nr_theirs) alternate_shallow_file = setup_temporary_shallow(si->shallow); else alternate_shallow_file = NULL; if (get_pack(args, fd, pack_lockfile)) die(_("git fetch-pack: fetch failed.")); all_done: negotiator.release(&negotiator); return ref; }
static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args, int fd[2], const struct ref *orig_ref, struct ref **sought, int nr_sought, char **pack_lockfile) { struct ref *ref = copy_ref_list(orig_ref); enum fetch_state state = FETCH_CHECK_LOCAL; struct oidset common = OIDSET_INIT; struct packet_reader reader; int in_vain = 0; int haves_to_send = INITIAL_FLUSH; struct fetch_negotiator negotiator; fetch_negotiator_init(&negotiator, negotiation_algorithm); packet_reader_init(&reader, fd[0], NULL, 0, PACKET_READ_CHOMP_NEWLINE); while (state != FETCH_DONE) { switch (state) { case FETCH_CHECK_LOCAL: sort_ref_list(&ref, ref_compare_name); QSORT(sought, nr_sought, cmp_ref_by_name); /* v2 supports these by default */ allow_unadvertised_object_request |= ALLOW_REACHABLE_SHA1; use_sideband = 2; if (args->depth > 0 || args->deepen_since || args->deepen_not) args->deepen = 1; /* Filter 'ref' by 'sought' and those that aren't local */ if (!args->no_dependents) { mark_complete_and_common_ref(&negotiator, args, &ref); filter_refs(args, &ref, sought, nr_sought); if (everything_local(args, &ref)) state = FETCH_DONE; else state = FETCH_SEND_REQUEST; mark_tips(&negotiator, args->negotiation_tips); for_each_cached_alternate(&negotiator, insert_one_alternate_object); } else { filter_refs(args, &ref, sought, nr_sought); state = FETCH_SEND_REQUEST; } break; case FETCH_SEND_REQUEST: if (send_fetch_request(&negotiator, fd[1], args, ref, &common, &haves_to_send, &in_vain)) state = FETCH_GET_PACK; else state = FETCH_PROCESS_ACKS; break; case FETCH_PROCESS_ACKS: /* Process ACKs/NAKs */ switch (process_acks(&negotiator, &reader, &common)) { case 2: state = FETCH_GET_PACK; break; case 1: in_vain = 0; /* fallthrough */ default: state = FETCH_SEND_REQUEST; break; } break; case FETCH_GET_PACK: /* Check for shallow-info section */ if (process_section_header(&reader, "shallow-info", 1)) receive_shallow_info(args, &reader); if (process_section_header(&reader, "wanted-refs", 1)) receive_wanted_refs(&reader, sought, nr_sought); /* get the pack */ process_section_header(&reader, "packfile", 0); if (get_pack(args, fd, pack_lockfile)) die(_("git fetch-pack: fetch failed.")); state = FETCH_DONE; break; case FETCH_DONE: continue; } } negotiator.release(&negotiator); oidset_clear(&common); return ref; }
static int everything_local(struct fetch_pack_args *args, struct ref **refs, struct ref **sought, int nr_sought) { struct ref *ref; int retval; int old_save_commit_buffer = save_commit_buffer; timestamp_t cutoff = 0; struct oidset loose_oid_set = OIDSET_INIT; int use_oidset = 0; struct loose_object_iter iter = {&loose_oid_set, *refs}; /* Enumerate all loose objects or know refs are not so many. */ use_oidset = !for_each_loose_object(add_loose_objects_to_set, &iter, 0); save_commit_buffer = 0; for (ref = *refs; ref; ref = ref->next) { struct object *o; unsigned int flags = OBJECT_INFO_QUICK; if (use_oidset && !oidset_contains(&loose_oid_set, &ref->old_oid)) { /* * I know this does not exist in the loose form, * so check if it exists in a non-loose form. */ flags |= OBJECT_INFO_IGNORE_LOOSE; } if (!has_object_file_with_flags(&ref->old_oid, flags)) continue; o = parse_object(&ref->old_oid); if (!o) continue; /* We already have it -- which may mean that we were * in sync with the other side at some time after * that (it is OK if we guess wrong here). */ if (o->type == OBJ_COMMIT) { struct commit *commit = (struct commit *)o; if (!cutoff || cutoff < commit->date) cutoff = commit->date; } } oidset_clear(&loose_oid_set); if (!args->no_dependents) { if (!args->deepen) { for_each_ref(mark_complete_oid, NULL); for_each_cached_alternate(mark_alternate_complete); commit_list_sort_by_date(&complete); if (cutoff) mark_recent_complete_commits(args, cutoff); } /* * Mark all complete remote refs as common refs. * Don't mark them common yet; the server has to be told so first. */ for (ref = *refs; ref; ref = ref->next) { struct object *o = deref_tag(lookup_object(ref->old_oid.hash), NULL, 0); if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE)) continue; if (!(o->flags & SEEN)) { rev_list_push((struct commit *)o, COMMON_REF | SEEN); mark_common((struct commit *)o, 1, 1); } } } filter_refs(args, refs, sought, nr_sought); for (retval = 1, ref = *refs; ref ; ref = ref->next) { const struct object_id *remote = &ref->old_oid; struct object *o; o = lookup_object(remote->hash); if (!o || !(o->flags & COMPLETE)) { retval = 0; print_verbose(args, "want %s (%s)", oid_to_hex(remote), ref->name); continue; } print_verbose(args, _("already have %s (%s)"), oid_to_hex(remote), ref->name); } save_commit_buffer = old_save_commit_buffer; return retval; }