static int pickaxe_match(struct diff_filepair *p, struct diff_options *o, regex_t *regexp, kwset_t kws, pickaxe_fn fn) { struct userdiff_driver *textconv_one = NULL; struct userdiff_driver *textconv_two = NULL; mmfile_t mf1, mf2; int ret; /* ignore unmerged */ if (!DIFF_FILE_VALID(p->one) && !DIFF_FILE_VALID(p->two)) return 0; if (o->objfind) { return (DIFF_FILE_VALID(p->one) && oidset_contains(o->objfind, &p->one->oid)) || (DIFF_FILE_VALID(p->two) && oidset_contains(o->objfind, &p->two->oid)); } if (!o->pickaxe[0]) return 0; if (o->flags.allow_textconv) { textconv_one = get_textconv(o->repo->index, p->one); textconv_two = get_textconv(o->repo->index, p->two); } /* * If we have an unmodified pair, we know that the count will be the * same and don't even have to load the blobs. Unless textconv is in * play, _and_ we are using two different textconv filters (e.g., * because a pair is an exact rename with different textconv attributes * for each side, which might generate different content). */ if (textconv_one == textconv_two && diff_unmodified_pair(p)) return 0; mf1.size = fill_textconv(o->repo, textconv_one, p->one, &mf1.ptr); mf2.size = fill_textconv(o->repo, textconv_two, p->two, &mf2.ptr); ret = fn(DIFF_FILE_VALID(p->one) ? &mf1 : NULL, DIFF_FILE_VALID(p->two) ? &mf2 : NULL, o, regexp, kws); if (textconv_one) free(mf1.ptr); if (textconv_two) free(mf2.ptr); diff_free_filespec_data(p->one); diff_free_filespec_data(p->two); return ret; }
static int fsck_blob(struct blob *blob, const char *buf, unsigned long size, struct fsck_options *options) { struct fsck_gitmodules_data data; if (!oidset_contains(&gitmodules_found, &blob->object.oid)) return 0; oidset_insert(&gitmodules_done, &blob->object.oid); if (!buf) { /* * A missing buffer here is a sign that the caller found the * blob too gigantic to load into memory. Let's just consider * that an error. */ return report(options, &blob->object, FSCK_MSG_GITMODULES_PARSE, ".gitmodules too large to parse"); } data.obj = &blob->object; data.options = options; data.ret = 0; if (git_config_from_mem(fsck_gitmodules_fn, CONFIG_ORIGIN_BLOB, ".gitmodules", buf, size, &data)) data.ret |= report(options, &blob->object, FSCK_MSG_GITMODULES_PARSE, "could not parse gitmodules blob"); return data.ret; }
int fsck_finish(struct fsck_options *options) { int ret = 0; struct oidset_iter iter; const struct object_id *oid; oidset_iter_init(&gitmodules_found, &iter); while ((oid = oidset_iter_next(&iter))) { struct blob *blob; enum object_type type; unsigned long size; char *buf; if (oidset_contains(&gitmodules_done, oid)) continue; blob = lookup_blob(oid); if (!blob) { struct object *obj = lookup_unknown_object(oid->hash); ret |= report(options, obj, FSCK_MSG_GITMODULES_BLOB, "non-blob found at .gitmodules"); continue; } buf = read_object_file(oid, &type, &size); if (!buf) { if (is_promisor_object(&blob->object.oid)) continue; ret |= report(options, &blob->object, FSCK_MSG_GITMODULES_MISSING, "unable to read .gitmodules blob"); continue; } if (type == OBJ_BLOB) ret |= fsck_blob(blob, buf, size, options); else ret |= report(options, &blob->object, FSCK_MSG_GITMODULES_BLOB, "non-blob found at .gitmodules"); free(buf); } oidset_clear(&gitmodules_found); oidset_clear(&gitmodules_done); return ret; }
static int tip_oids_contain(struct oidset *tip_oids, struct ref *unmatched, struct ref *newlist, const struct object_id *id) { /* * Note that this only looks at the ref lists the first time it's * called. This works out in filter_refs() because even though it may * add to "newlist" between calls, the additions will always be for * oids that are already in the set. */ if (!tip_oids->map.map.tablesize) { add_refs_to_oidset(tip_oids, unmatched); add_refs_to_oidset(tip_oids, newlist); } return oidset_contains(tip_oids, id); }
/* * 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; 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(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; } } oidset_clear(&loose_oid_set); 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; }
static void filter_refs(struct fetch_pack_args *args, struct ref **refs, struct ref **sought, int nr_sought) { struct ref *newlist = NULL; struct ref **newtail = &newlist; struct ref *unmatched = NULL; struct ref *ref, *next; struct oidset tip_oids = OIDSET_INIT; int i; int strict = !(allow_unadvertised_object_request & (ALLOW_TIP_SHA1 | ALLOW_REACHABLE_SHA1)); i = 0; for (ref = *refs; ref; ref = next) { int keep = 0; next = ref->next; if (starts_with(ref->name, "refs/") && check_refname_format(ref->name, 0)) ; /* trash */ else { while (i < nr_sought) { int cmp = strcmp(ref->name, sought[i]->name); if (cmp < 0) break; /* definitely do not have it */ else if (cmp == 0) { keep = 1; /* definitely have it */ sought[i]->match_status = REF_MATCHED; } i++; } if (!keep && args->fetch_all && (!args->deepen || !starts_with(ref->name, "refs/tags/"))) keep = 1; } if (keep) { *newtail = ref; ref->next = NULL; newtail = &ref->next; } else { ref->next = unmatched; unmatched = ref; } } if (strict) { for (i = 0; i < nr_sought; i++) { ref = sought[i]; if (!is_unmatched_ref(ref)) continue; add_refs_to_oidset(&tip_oids, unmatched); add_refs_to_oidset(&tip_oids, newlist); break; } } /* Append unmatched requests to the list */ for (i = 0; i < nr_sought; i++) { ref = sought[i]; if (!is_unmatched_ref(ref)) continue; if (!strict || oidset_contains(&tip_oids, &ref->old_oid)) { ref->match_status = REF_MATCHED; *newtail = copy_ref(ref); newtail = &(*newtail)->next; } else { ref->match_status = REF_UNADVERTISED_NOT_ALLOWED; } } oidset_clear(&tip_oids); for (ref = unmatched; ref; ref = next) { next = ref->next; free(ref); } *refs = newlist; }
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; }