static void snarf_refs(int head, int remotes) { if (head) { int orig_cnt = ref_name_cnt; for_each_ref(append_head_ref, NULL); sort_ref_range(orig_cnt, ref_name_cnt); } if (remotes) { int orig_cnt = ref_name_cnt; for_each_ref(append_remote_ref, NULL); sort_ref_range(orig_cnt, ref_name_cnt); } }
static void snarf_refs(int head, int tag) { if (head) { int orig_cnt = ref_name_cnt; for_each_ref(append_head_ref); sort_ref_range(orig_cnt, ref_name_cnt); } if (tag) { int orig_cnt = ref_name_cnt; for_each_ref(append_tag_ref); sort_ref_range(orig_cnt, ref_name_cnt); } }
int for_each_glob_ref_in(each_ref_fn fn, const char *pattern, const char *prefix, void *cb_data) { struct strbuf real_pattern = STRBUF_INIT; struct ref_filter filter; int ret; if (!prefix && prefixcmp(pattern, "refs/")) strbuf_addstr(&real_pattern, "refs/"); else if (prefix) strbuf_addstr(&real_pattern, prefix); strbuf_addstr(&real_pattern, pattern); if (!has_glob_specials(pattern)) { /* Append implied '/' '*' if not present. */ if (real_pattern.buf[real_pattern.len - 1] != '/') strbuf_addch(&real_pattern, '/'); /* No need to check for '*', there is none. */ strbuf_addch(&real_pattern, '*'); } filter.pattern = real_pattern.buf; filter.fn = fn; filter.cb_data = cb_data; ret = for_each_ref(filter_refs, &filter); strbuf_release(&real_pattern); return ret; }
int pack_refs(unsigned int flags) { int fd; struct pack_refs_cb_data cbdata; memset(&cbdata, 0, sizeof(cbdata)); cbdata.flags = flags; fd = hold_lock_file_for_update(&packed, git_path("packed-refs"), 1); cbdata.refs_file = fdopen(fd, "w"); if (!cbdata.refs_file) die("unable to create ref-pack file structure (%s)", strerror(errno)); /* perhaps other traits later as well */ fprintf(cbdata.refs_file, "# pack-refs with: peeled \n"); for_each_ref(handle_one_ref, &cbdata); if (ferror(cbdata.refs_file)) die("failed to write ref-pack file"); if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file)) die("failed to write ref-pack file (%s)", strerror(errno)); /* * Since the lock file was fdopen()'ed and then fclose()'ed above, * assign -1 to the lock file descriptor so that commit_lock_file() * won't try to close() it. */ packed.fd = -1; if (commit_lock_file(&packed) < 0) die("unable to overwrite old ref-pack file (%s)", strerror(errno)); if (cbdata.flags & PACK_REFS_PRUNE) prune_refs(cbdata.ref_to_prune); return 0; }
static void write_head_info(void) { for_each_ref(show_ref_cb, NULL); if (!sent_capabilities) show_ref("capabilities^{}", null_sha1, 0, NULL); }
static void cmd_log_init(int argc, const char **argv, const char *prefix, struct rev_info *rev) { int i; int decorate = 0; rev->abbrev = DEFAULT_ABBREV; rev->commit_format = CMIT_FMT_DEFAULT; if (fmt_pretty) get_commit_format(fmt_pretty, rev); rev->verbose_header = 1; DIFF_OPT_SET(&rev->diffopt, RECURSIVE); rev->show_root_diff = default_show_root; rev->subject_prefix = fmt_patch_subject_prefix; argc = setup_revisions(argc, argv, rev, "HEAD"); if (rev->diffopt.pickaxe || rev->diffopt.filter) rev->always_show_header = 0; if (DIFF_OPT_TST(&rev->diffopt, FOLLOW_RENAMES)) { rev->always_show_header = 0; if (rev->diffopt.nr_paths != 1) usage("git logs can only follow renames on one pathname at a time"); } for (i = 1; i < argc; i++) { const char *arg = argv[i]; if (!strcmp(arg, "--decorate")) { if (!decorate) for_each_ref(add_ref_decoration, NULL); decorate = 1; } else die("unrecognized argument: %s", arg); } }
static void write_head_info(void) { for_each_ref(show_ref, NULL); if (capabilities_to_send) show_ref("capabilities^{}", null_sha1, 0, NULL); }
static void get_info_refs(char *arg) { const char *service_name = get_parameter("service"); struct strbuf buf = STRBUF_INIT; hdr_nocache(); if (service_name) { const char *argv[] = {NULL /* service name */, "--stateless-rpc", "--advertise-refs", ".", NULL}; struct rpc_service *svc = select_service(service_name); strbuf_addf(&buf, "application/x-git-%s-advertisement", svc->name); hdr_str(content_type, buf.buf); end_headers(); packet_write(1, "# service=git-%s\n", svc->name); packet_flush(1); argv[0] = svc->name; run_service(argv); } else { select_getanyfile(); for_each_ref(show_text_ref, &buf); send_strbuf("text/plain", &buf); } strbuf_release(&buf); }
int gidit_pushobj(FILE *fp, char * signingkey, int sign, unsigned int flags) { const char *head; unsigned char head_sha1[21]; struct gidit_refs_cb_data cbdata; struct strbuf buf = STRBUF_INIT; cbdata.buf = &buf; cbdata.flags = flags; head = resolve_ref("HEAD", head_sha1, 0, NULL); head_sha1[20] = '\0'; if (!head) { strbuf_release(&buf); return error("Failed to resolve HEAD as a valid ref."); } strbuf_add(&buf, sha1_to_hex(head_sha1), 40); strbuf_addstr(&buf, " HEAD\n"); for_each_ref(resolve_one_ref, &cbdata); if (sign) do_sign(&buf, signingkey); if (fwrite(buf.buf, buf.len, 1, fp) != 1) { strbuf_release(&buf); return error("Error while writing pushobj"); } strbuf_release(&buf); return 0; }
void load_ref_decorations(int flags) { static int loaded; if (!loaded) { loaded = 1; for_each_ref(add_ref_decoration, &flags); } }
void load_ref_decorations(void) { static int loaded; if (!loaded) { loaded = 1; for_each_ref(add_ref_decoration, NULL); } }
/* * Mark recent commits available locally and reachable from a local ref as * COMPLETE. If args->no_dependents is false, also mark COMPLETE remote refs as * COMMON_REF (otherwise, we are not planning to participate in negotiation, and * thus do not need COMMON_REF marks). * * The cutoff time for recency is determined by this heuristic: it is the * earliest commit time of the objects in refs that are commits and that we know * the commit time of. */ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator, struct fetch_pack_args *args, struct ref **refs) { struct ref *ref; int old_save_commit_buffer = save_commit_buffer; timestamp_t cutoff = 0; save_commit_buffer = 0; for (ref = *refs; ref; ref = ref->next) { struct object *o; if (!has_object_file_with_flags(&ref->old_oid, OBJECT_INFO_QUICK)) continue; o = parse_object(the_repository, &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; } } if (!args->deepen) { for_each_ref(mark_complete_oid, NULL); for_each_cached_alternate(NULL, 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(the_repository, lookup_object(the_repository, ref->old_oid.hash), NULL, 0); if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE)) continue; negotiator->known_common(negotiator, (struct commit *)o); } save_commit_buffer = old_save_commit_buffer; }
void check_for_new_submodule_commits(unsigned char new_sha1[20]) { if (!initialized_fetch_ref_tips) { for_each_ref(add_sha1_to_array, &ref_tips_before_fetch); initialized_fetch_ref_tips = 1; } sha1_array_append(&ref_tips_after_fetch, new_sha1); }
void cgit_clone_info(void) { if (!ctx.qry.path || strcmp(ctx.qry.path, "refs")) return; ctx.page.mimetype = "text/plain"; ctx.page.filename = "info/refs"; cgit_print_http_headers(); for_each_ref(print_ref_info, NULL); }
void load_ref_decorations(int flags) { static int loaded; if (!loaded) { loaded = 1; for_each_ref(add_ref_decoration, &flags); head_ref(add_ref_decoration, &flags); for_each_commit_graft(add_graft_decoration, NULL); } }
static struct string_list guess_refs(const char *ref) { struct similar_ref_cb ref_cb; struct string_list similar_refs = STRING_LIST_INIT_NODUP; ref_cb.base_ref = ref; ref_cb.similar_refs = &similar_refs; for_each_ref(append_similar_ref, &ref_cb); return similar_refs; }
static void upload_pack(void) { if (advertise_refs || !stateless_rpc) { reset_timeout(); head_ref(send_ref, NULL); for_each_ref(send_ref, NULL); packet_flush(1); } else { head_ref(mark_our_ref, NULL); for_each_ref(mark_our_ref, NULL); } if (advertise_refs) return; receive_needs(); if (want_obj.nr) { get_common_commits(); create_pack_file(); } }
void load_ref_decorations(int flags) { if (!decoration_loaded) { decoration_loaded = 1; decoration_flags = flags; for_each_ref(add_ref_decoration, NULL); head_ref(add_ref_decoration, NULL); for_each_commit_graft(add_graft_decoration, NULL); } }
void cgit_clone_info(void) { if (!ctx.qry.path || strcmp(ctx.qry.path, "refs")) { cgit_print_error_page(400, "Bad request", "Bad request"); return; } ctx.page.mimetype = "text/plain"; ctx.page.filename = "info/refs"; cgit_print_http_headers(); for_each_ref(print_ref_info, NULL); }
static void upload_pack(void) { reset_timeout(); head_ref(send_ref, NULL); for_each_ref(send_ref, NULL); packet_flush(1); receive_needs(); if (want_obj.nr) { get_common_commits(); create_pack_file(); } }
static void find_non_local_tags(struct transport *transport, struct ref **head, struct ref ***tail) { struct string_list existing_refs = { NULL, 0, 0, 0 }; struct string_list new_refs = { NULL, 0, 0, 1 }; char *ref_name; int ref_name_len; const unsigned char *ref_sha1; const struct ref *tag_ref; struct ref *rm = NULL; const struct ref *ref; for_each_ref(add_existing, &existing_refs); for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) { if (prefixcmp(ref->name, "refs/tags")) continue; ref_name = xstrdup(ref->name); ref_name_len = strlen(ref_name); ref_sha1 = ref->old_sha1; if (!strcmp(ref_name + ref_name_len - 3, "^{}")) { ref_name[ref_name_len - 3] = 0; tag_ref = transport_get_remote_refs(transport); while (tag_ref) { if (!strcmp(tag_ref->name, ref_name)) { ref_sha1 = tag_ref->old_sha1; break; } tag_ref = tag_ref->next; } } if (!string_list_has_string(&existing_refs, ref_name) && !string_list_has_string(&new_refs, ref_name) && (has_sha1_file(ref->old_sha1) || will_fetch(head, ref->old_sha1))) { string_list_insert(ref_name, &new_refs); rm = alloc_ref(ref_name); rm->peer_ref = alloc_ref(ref_name); hashcpy(rm->old_sha1, ref_sha1); **tail = rm; *tail = &rm->next; } free(ref_name); } string_list_clear(&existing_refs, 0); string_list_clear(&new_refs, 0); }
static void write_head_info(void) { struct sha1_array sa = SHA1_ARRAY_INIT; for_each_alternate_ref(collect_one_alternate_ref, &sa); sha1_array_for_each_unique(&sa, show_one_alternate_sha1, NULL); sha1_array_clear(&sa); for_each_ref(show_ref_cb, NULL); if (!sent_capabilities) show_ref("capabilities^{}", null_sha1); /* EOF */ packet_flush(1); }
static void print_ref_list(int kinds, int detached, int verbose, int abbrev, struct commit_list *with_commit) { int i; struct ref_list ref_list; struct commit *head_commit = lookup_commit_reference_gently(head_sha1, 1); memset(&ref_list, 0, sizeof(ref_list)); ref_list.kinds = kinds; ref_list.with_commit = with_commit; if (merge_filter != NO_FILTER) init_revisions(&ref_list.revs, NULL); for_each_ref(append_ref, &ref_list); if (merge_filter != NO_FILTER) { struct commit *filter; filter = lookup_commit_reference_gently(merge_filter_ref, 0); filter->object.flags |= UNINTERESTING; add_pending_object(&ref_list.revs, (struct object *) filter, ""); ref_list.revs.limited = 1; prepare_revision_walk(&ref_list.revs); if (verbose) ref_list.maxwidth = calc_maxwidth(&ref_list); } qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp); detached = (detached && (kinds & REF_LOCAL_BRANCH)); if (detached && head_commit && is_descendant_of(head_commit, with_commit)) { struct ref_item item; item.name = xstrdup("(no branch)"); item.kind = REF_LOCAL_BRANCH; item.commit = head_commit; if (strlen(item.name) > ref_list.maxwidth) ref_list.maxwidth = strlen(item.name); print_ref_item(&item, ref_list.maxwidth, verbose, abbrev, 1); free(item.name); } for (i = 0; i < ref_list.index; i++) { int current = !detached && (ref_list.list[i].kind == REF_LOCAL_BRANCH) && !strcmp(ref_list.list[i].name, head); print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose, abbrev, current); } free_ref_list(&ref_list); }
static void mark_tips(struct fetch_negotiator *negotiator, const struct oid_array *negotiation_tips) { int i; if (!negotiation_tips) { for_each_ref(rev_list_insert_ref_oid, negotiator); return; } for (i = 0; i < negotiation_tips->nr; i++) rev_list_insert_ref(negotiator, NULL, &negotiation_tips->oid[i]); return; }
int cmd_show_ref(int argc, const char **argv, const char *prefix) { if (argc == 2 && !strcmp(argv[1], "-h")) usage_with_options(show_ref_usage, show_ref_options); argc = parse_options(argc, argv, prefix, show_ref_options, show_ref_usage, PARSE_OPT_NO_INTERNAL_HELP); if (exclude_arg) return exclude_existing(exclude_existing_arg); pattern = argv; if (!*pattern) pattern = NULL; if (verify) { if (!pattern) die("--verify requires a reference"); while (*pattern) { unsigned char sha1[20]; if (!prefixcmp(*pattern, "refs/") && !read_ref(*pattern, sha1)) { if (!quiet) show_one(*pattern, sha1); } else if (!quiet) die("'%s' - not a valid ref", *pattern); else return 1; pattern++; } return 0; } if (show_head) head_ref(show_ref, NULL); for_each_ref(show_ref, NULL); if (!found_match) { if (verify && !quiet) die("No match"); return 1; } return 0; }
int cmd_show_ref(int argc, const char **argv, const char *prefix) { git_config(git_default_config, NULL); argc = parse_options(argc, argv, prefix, show_ref_options, show_ref_usage, 0); if (exclude_arg) return exclude_existing(exclude_existing_arg); pattern = argv; if (!*pattern) pattern = NULL; if (verify) { if (!pattern) die("--verify requires a reference"); while (*pattern) { struct object_id oid; if ((starts_with(*pattern, "refs/") || !strcmp(*pattern, "HEAD")) && !read_ref(*pattern, &oid)) { show_one(*pattern, &oid); } else if (!quiet) die("'%s' - not a valid ref", *pattern); else return 1; pattern++; } return 0; } if (show_head) head_ref(show_ref, NULL); for_each_ref(show_ref, NULL); if (!found_match) { if (verify && !quiet) die("No match"); return 1; } return 0; }
static void append_one_rev(const char *av) { unsigned char revkey[20]; if (!get_sha1(av, revkey)) { append_ref(av, revkey, 0); return; } if (strchr(av, '*') || strchr(av, '?') || strchr(av, '[')) { /* glob style match */ int saved_matches = ref_name_cnt; match_ref_pattern = av; match_ref_slash = count_slash(av); for_each_ref(append_matching_ref, NULL); if (saved_matches == ref_name_cnt && ref_name_cnt < MAX_REVS) error("no matching refs with %s", av); if (saved_matches + 1 < ref_name_cnt) sort_ref_range(saved_matches, ref_name_cnt); return; } die("bad sha1 reference %s", av); }
/* * read "^(?:<anything>\s)?<refname>(?:\^\{\})?$" from the standard input, * and * (1) strip "^{}" at the end of line if any; * (2) ignore if match is provided and does not head-match refname; * (3) warn if refname is not a well-formed refname and skip; * (4) ignore if refname is a ref that exists in the local repository; * (5) otherwise output the line. */ static int exclude_existing(const char *match) { static struct string_list existing_refs = STRING_LIST_INIT_DUP; char buf[1024]; int matchlen = match ? strlen(match) : 0; for_each_ref(add_existing, &existing_refs); while (fgets(buf, sizeof(buf), stdin)) { char *ref; int len = strlen(buf); if (len > 0 && buf[len - 1] == '\n') buf[--len] = '\0'; if (3 <= len && !strcmp(buf + len - 3, "^{}")) { len -= 3; buf[len] = '\0'; } for (ref = buf + len; buf < ref; ref--) if (isspace(ref[-1])) break; if (match) { int reflen = buf + len - ref; if (reflen < matchlen) continue; if (strncmp(ref, match, matchlen)) continue; } if (check_refname_format(ref, 0)) { warning("ref '%s' ignored", ref); continue; } if (!string_list_has_string(&existing_refs, ref)) { printf("%s\n", buf); } } return 0; }
static void reflog_expiry_prepare(const char *refname, const struct object_id *oid, void *cb_data) { struct expire_reflog_policy_cb *cb = cb_data; if (!cb->cmd.expire_unreachable || is_head(refname)) { cb->tip_commit = NULL; cb->unreachable_expire_kind = UE_HEAD; } else { cb->tip_commit = lookup_commit_reference_gently(the_repository, oid, 1); if (!cb->tip_commit) cb->unreachable_expire_kind = UE_ALWAYS; else cb->unreachable_expire_kind = UE_NORMAL; } if (cb->cmd.expire_unreachable <= cb->cmd.expire_total) cb->unreachable_expire_kind = UE_ALWAYS; cb->mark_list = NULL; cb->tips = NULL; if (cb->unreachable_expire_kind != UE_ALWAYS) { if (cb->unreachable_expire_kind == UE_HEAD) { struct commit_list *elem; for_each_ref(push_tip_to_list, &cb->tips); for (elem = cb->tips; elem; elem = elem->next) commit_list_insert(elem->item, &cb->mark_list); } else { commit_list_insert(cb->tip_commit, &cb->mark_list); } cb->mark_limit = cb->cmd.expire_total; mark_reachable(cb); } }
/* * We are about to leave commit that was at the tip of a detached * HEAD. If it is not reachable from any ref, this is the last chance * for the user to do so without resorting to reflog. */ static void orphaned_commit_warning(struct commit *old_commit, struct commit *new_commit) { struct rev_info revs; struct object *object = &old_commit->object; repo_init_revisions(the_repository, &revs, NULL); setup_revisions(0, NULL, &revs, NULL); object->flags &= ~UNINTERESTING; add_pending_object(&revs, object, oid_to_hex(&object->oid)); for_each_ref(add_pending_uninteresting_ref, &revs); add_pending_oid(&revs, "HEAD", &new_commit->object.oid, UNINTERESTING); if (prepare_revision_walk(&revs)) die(_("internal error in revision walk")); if (!(old_commit->object.flags & UNINTERESTING)) suggest_reattach(old_commit, &revs); else describe_detached_head(_("Previous HEAD position was"), old_commit); /* Clean up objects used, as they will be reused. */ clear_commit_marks_all(ALL_REV_FLAGS); }