diff options
Diffstat (limited to 'third_party/git/ref-filter.c')
-rw-r--r-- | third_party/git/ref-filter.c | 331 |
1 files changed, 202 insertions, 129 deletions
diff --git a/third_party/git/ref-filter.c b/third_party/git/ref-filter.c index f27cfc8c3e35..c62f6b482271 100644 --- a/third_party/git/ref-filter.c +++ b/third_party/git/ref-filter.c @@ -22,7 +22,7 @@ #include "commit-reach.h" #include "worktree.h" #include "hashmap.h" -#include "argv-array.h" +#include "strvec.h" static struct ref_msg { const char *gone; @@ -79,17 +79,20 @@ static struct expand_data { } oi, oi_deref; struct ref_to_worktree_entry { - struct hashmap_entry ent; /* must be the first member! */ + struct hashmap_entry ent; struct worktree *wt; /* key is wt->head_ref */ }; static int ref_to_worktree_map_cmpfnc(const void *unused_lookupdata, - const void *existing_hashmap_entry_to_test, - const void *key, + const struct hashmap_entry *eptr, + const struct hashmap_entry *kptr, const void *keydata_aka_refname) { - const struct ref_to_worktree_entry *e = existing_hashmap_entry_to_test; - const struct ref_to_worktree_entry *k = key; + const struct ref_to_worktree_entry *e, *k; + + e = container_of(eptr, const struct ref_to_worktree_entry, ent); + k = container_of(kptr, const struct ref_to_worktree_entry, ent); + return strcmp(e->wt->head_ref, keydata_aka_refname ? keydata_aka_refname : k->wt->head_ref); } @@ -124,7 +127,8 @@ static struct used_atom { unsigned int nobracket : 1, push : 1, push_remote : 1; } remote_ref; struct { - enum { C_BARE, C_BODY, C_BODY_DEP, C_LINES, C_SIG, C_SUB, C_TRAILERS } option; + enum { C_BARE, C_BODY, C_BODY_DEP, C_LENGTH, C_LINES, + C_SIG, C_SUB, C_SUB_SANITIZE, C_TRAILERS } option; struct process_trailer_options trailer_opts; unsigned int nlines; } contents; @@ -135,7 +139,10 @@ static struct used_atom { struct { enum { O_FULL, O_LENGTH, O_SHORT } option; unsigned int length; - } objectname; + } oid; + struct email_option { + enum { EO_RAW, EO_TRIM, EO_LOCALPART } option; + } email_option; struct refname_atom refname; char *head; } u; @@ -276,9 +283,9 @@ static int deltabase_atom_parser(const struct ref_format *format, struct used_at if (arg) return strbuf_addf_ret(err, -1, _("%%(deltabase) does not take arguments")); if (*atom->name == '*') - oi_deref.info.delta_base_sha1 = oi_deref.delta_base_oid.hash; + oi_deref.info.delta_base_oid = &oi_deref.delta_base_oid; else - oi.info.delta_base_sha1 = oi.delta_base_oid.hash; + oi.info.delta_base_oid = &oi.delta_base_oid; return 0; } @@ -294,9 +301,12 @@ static int body_atom_parser(const struct ref_format *format, struct used_atom *a static int subject_atom_parser(const struct ref_format *format, struct used_atom *atom, const char *arg, struct strbuf *err) { - if (arg) - return strbuf_addf_ret(err, -1, _("%%(subject) does not take arguments")); - atom->u.contents.option = C_SUB; + if (!arg) + atom->u.contents.option = C_SUB; + else if (!strcmp(arg, "sanitize")) + atom->u.contents.option = C_SUB_SANITIZE; + else + return strbuf_addf_ret(err, -1, _("unrecognized %%(subject) argument: %s"), arg); return 0; } @@ -335,13 +345,17 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato atom->u.contents.option = C_BARE; else if (!strcmp(arg, "body")) atom->u.contents.option = C_BODY; + else if (!strcmp(arg, "size")) + atom->u.contents.option = C_LENGTH; else if (!strcmp(arg, "signature")) atom->u.contents.option = C_SIG; else if (!strcmp(arg, "subject")) atom->u.contents.option = C_SUB; - else if (skip_prefix(arg, "trailers", &arg)) { - skip_prefix(arg, ":", &arg); - if (trailers_atom_parser(format, atom, *arg ? arg : NULL, err)) + else if (!strcmp(arg, "trailers")) { + if (trailers_atom_parser(format, atom, NULL, err)) + return -1; + } else if (skip_prefix(arg, "trailers:", &arg)) { + if (trailers_atom_parser(format, atom, arg, err)) return -1; } else if (skip_prefix(arg, "lines=", &arg)) { atom->u.contents.option = C_LINES; @@ -352,22 +366,36 @@ static int contents_atom_parser(const struct ref_format *format, struct used_ato return 0; } -static int objectname_atom_parser(const struct ref_format *format, struct used_atom *atom, - const char *arg, struct strbuf *err) +static int oid_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) { if (!arg) - atom->u.objectname.option = O_FULL; + atom->u.oid.option = O_FULL; else if (!strcmp(arg, "short")) - atom->u.objectname.option = O_SHORT; + atom->u.oid.option = O_SHORT; else if (skip_prefix(arg, "short=", &arg)) { - atom->u.objectname.option = O_LENGTH; - if (strtoul_ui(arg, 10, &atom->u.objectname.length) || - atom->u.objectname.length == 0) - return strbuf_addf_ret(err, -1, _("positive value expected objectname:short=%s"), arg); - if (atom->u.objectname.length < MINIMUM_ABBREV) - atom->u.objectname.length = MINIMUM_ABBREV; + atom->u.oid.option = O_LENGTH; + if (strtoul_ui(arg, 10, &atom->u.oid.length) || + atom->u.oid.length == 0) + return strbuf_addf_ret(err, -1, _("positive value expected '%s' in %%(%s)"), arg, atom->name); + if (atom->u.oid.length < MINIMUM_ABBREV) + atom->u.oid.length = MINIMUM_ABBREV; } else - return strbuf_addf_ret(err, -1, _("unrecognized %%(objectname) argument: %s"), arg); + return strbuf_addf_ret(err, -1, _("unrecognized argument '%s' in %%(%s)"), arg, atom->name); + return 0; +} + +static int person_email_atom_parser(const struct ref_format *format, struct used_atom *atom, + const char *arg, struct strbuf *err) +{ + if (!arg) + atom->u.email_option.option = EO_RAW; + else if (!strcmp(arg, "trim")) + atom->u.email_option.option = EO_TRIM; + else if (!strcmp(arg, "localpart")) + atom->u.email_option.option = EO_LOCALPART; + else + return strbuf_addf_ret(err, -1, _("unrecognized email option: %s"), arg); return 0; } @@ -472,25 +500,25 @@ static struct { { "refname", SOURCE_NONE, FIELD_STR, refname_atom_parser }, { "objecttype", SOURCE_OTHER, FIELD_STR, objecttype_atom_parser }, { "objectsize", SOURCE_OTHER, FIELD_ULONG, objectsize_atom_parser }, - { "objectname", SOURCE_OTHER, FIELD_STR, objectname_atom_parser }, + { "objectname", SOURCE_OTHER, FIELD_STR, oid_atom_parser }, { "deltabase", SOURCE_OTHER, FIELD_STR, deltabase_atom_parser }, - { "tree", SOURCE_OBJ }, - { "parent", SOURCE_OBJ }, + { "tree", SOURCE_OBJ, FIELD_STR, oid_atom_parser }, + { "parent", SOURCE_OBJ, FIELD_STR, oid_atom_parser }, { "numparent", SOURCE_OBJ, FIELD_ULONG }, { "object", SOURCE_OBJ }, { "type", SOURCE_OBJ }, { "tag", SOURCE_OBJ }, { "author", SOURCE_OBJ }, { "authorname", SOURCE_OBJ }, - { "authoremail", SOURCE_OBJ }, + { "authoremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser }, { "authordate", SOURCE_OBJ, FIELD_TIME }, { "committer", SOURCE_OBJ }, { "committername", SOURCE_OBJ }, - { "committeremail", SOURCE_OBJ }, + { "committeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser }, { "committerdate", SOURCE_OBJ, FIELD_TIME }, { "tagger", SOURCE_OBJ }, { "taggername", SOURCE_OBJ }, - { "taggeremail", SOURCE_OBJ }, + { "taggeremail", SOURCE_OBJ, FIELD_STR, person_email_atom_parser }, { "taggerdate", SOURCE_OBJ, FIELD_TIME }, { "creator", SOURCE_OBJ }, { "creatordate", SOURCE_OBJ, FIELD_TIME }, @@ -895,21 +923,27 @@ int verify_ref_format(struct ref_format *format) return 0; } -static int grab_objectname(const char *name, const struct object_id *oid, - struct atom_value *v, struct used_atom *atom) +static const char *do_grab_oid(const char *field, const struct object_id *oid, + struct used_atom *atom) { - if (starts_with(name, "objectname")) { - if (atom->u.objectname.option == O_SHORT) { - v->s = xstrdup(find_unique_abbrev(oid, DEFAULT_ABBREV)); - return 1; - } else if (atom->u.objectname.option == O_FULL) { - v->s = xstrdup(oid_to_hex(oid)); - return 1; - } else if (atom->u.objectname.option == O_LENGTH) { - v->s = xstrdup(find_unique_abbrev(oid, atom->u.objectname.length)); - return 1; - } else - BUG("unknown %%(objectname) option"); + switch (atom->u.oid.option) { + case O_FULL: + return oid_to_hex(oid); + case O_LENGTH: + return find_unique_abbrev(oid, atom->u.oid.length); + case O_SHORT: + return find_unique_abbrev(oid, DEFAULT_ABBREV); + default: + BUG("unknown %%(%s) option", field); + } +} + +static int grab_oid(const char *name, const char *field, const struct object_id *oid, + struct atom_value *v, struct used_atom *atom) +{ + if (starts_with(name, field)) { + v->s = xstrdup(do_grab_oid(field, oid, atom)); + return 1; } return 0; } @@ -937,7 +971,7 @@ static void grab_common_values(struct atom_value *val, int deref, struct expand_ } else if (!strcmp(name, "deltabase")) v->s = xstrdup(oid_to_hex(&oi->delta_base_oid)); else if (deref) - grab_objectname(name, &oi->oid, v, &used_atom[i]); + grab_oid(name, "objectname", &oi->oid, v, &used_atom[i]); } } @@ -976,21 +1010,20 @@ static void grab_commit_values(struct atom_value *val, int deref, struct object continue; if (deref) name++; - if (!strcmp(name, "tree")) { - v->s = xstrdup(oid_to_hex(get_commit_tree_oid(commit))); - } - else if (!strcmp(name, "numparent")) { + if (grab_oid(name, "tree", get_commit_tree_oid(commit), v, &used_atom[i])) + continue; + if (!strcmp(name, "numparent")) { v->value = commit_list_count(commit->parents); v->s = xstrfmt("%lu", (unsigned long)v->value); } - else if (!strcmp(name, "parent")) { + else if (starts_with(name, "parent")) { struct commit_list *parents; struct strbuf s = STRBUF_INIT; for (parents = commit->parents; parents; parents = parents->next) { - struct commit *parent = parents->item; + struct object_id *oid = &parents->item->object.oid; if (parents != commit->parents) strbuf_addch(&s, ' '); - strbuf_addstr(&s, oid_to_hex(&parent->object.oid)); + strbuf_addstr(&s, do_grab_oid("parent", oid, &used_atom[i])); } v->s = strbuf_detach(&s, NULL); } @@ -1028,19 +1061,38 @@ static const char *copy_name(const char *buf) if (!strncmp(cp, " <", 2)) return xmemdupz(buf, cp - buf); } - return ""; + return xstrdup(""); } -static const char *copy_email(const char *buf) +static const char *copy_email(const char *buf, struct used_atom *atom) { const char *email = strchr(buf, '<'); const char *eoemail; if (!email) - return ""; - eoemail = strchr(email, '>'); + return xstrdup(""); + switch (atom->u.email_option.option) { + case EO_RAW: + eoemail = strchr(email, '>'); + if (eoemail) + eoemail++; + break; + case EO_TRIM: + email++; + eoemail = strchr(email, '>'); + break; + case EO_LOCALPART: + email++; + eoemail = strchr(email, '@'); + if (!eoemail) + eoemail = strchr(email, '>'); + break; + default: + BUG("unknown email option"); + } + if (!eoemail) - return ""; - return xmemdupz(email, eoemail + 1 - email); + return xstrdup(""); + return xmemdupz(email, eoemail - email); } static char *copy_subject(const char *buf, unsigned long len) @@ -1110,7 +1162,7 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void continue; if (name[wholen] != 0 && strcmp(name + wholen, "name") && - strcmp(name + wholen, "email") && + !starts_with(name + wholen, "email") && !starts_with(name + wholen, "date")) continue; if (!wholine) @@ -1121,8 +1173,8 @@ static void grab_person(const char *who, struct atom_value *val, int deref, void v->s = copy_line(wholine); else if (!strcmp(name + wholen, "name")) v->s = copy_name(wholine); - else if (!strcmp(name + wholen, "email")) - v->s = copy_email(wholine); + else if (starts_with(name + wholen, "email")) + v->s = copy_email(wholine, &used_atom[i]); else if (starts_with(name + wholen, "date")) grab_date(wholine, v, name); } @@ -1235,8 +1287,8 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf) continue; if (deref) name++; - if (strcmp(name, "subject") && - strcmp(name, "body") && + if (strcmp(name, "body") && + !starts_with(name, "subject") && !starts_with(name, "trailers") && !starts_with(name, "contents")) continue; @@ -1248,8 +1300,14 @@ static void grab_sub_body_contents(struct atom_value *val, int deref, void *buf) if (atom->u.contents.option == C_SUB) v->s = copy_subject(subpos, sublen); - else if (atom->u.contents.option == C_BODY_DEP) + else if (atom->u.contents.option == C_SUB_SANITIZE) { + struct strbuf sb = STRBUF_INIT; + format_sanitized_subject(&sb, subpos, sublen); + v->s = strbuf_detach(&sb, NULL); + } else if (atom->u.contents.option == C_BODY_DEP) v->s = xmemdupz(bodypos, bodylen); + else if (atom->u.contents.option == C_LENGTH) + v->s = xstrfmt("%"PRIuMAX, (uintmax_t)strlen(subpos)); else if (atom->u.contents.option == C_BODY) v->s = xmemdupz(bodypos, nonsiglen); else if (atom->u.contents.option == C_SIG) @@ -1456,12 +1514,10 @@ static void fill_remote_ref_details(struct used_atom *atom, const char *refname, remote_for_branch(branch, &explicit); *s = xstrdup(explicit ? remote : ""); } else if (atom->u.remote_ref.option == RR_REMOTE_REF) { - int explicit; const char *merge; - merge = remote_ref_for_branch(branch, atom->u.remote_ref.push, - &explicit); - *s = xstrdup(explicit ? merge : ""); + merge = remote_ref_for_branch(branch, atom->u.remote_ref.push); + *s = xstrdup(merge ? merge : ""); } else BUG("unhandled RR_* enum"); } @@ -1501,9 +1557,7 @@ char *get_head_description(void) strbuf_addstr(&desc, _("no branch")); strbuf_addch(&desc, ')'); - free(state.branch); - free(state.onto); - free(state.detached_from); + wt_status_state_free_buffers(&state); return strbuf_detach(&desc, NULL); } @@ -1565,9 +1619,10 @@ static void populate_worktree_map(struct hashmap *map, struct worktree **worktre struct ref_to_worktree_entry *entry; entry = xmalloc(sizeof(*entry)); entry->wt = worktrees[i]; - hashmap_entry_init(entry, strhash(worktrees[i]->head_ref)); + hashmap_entry_init(&entry->ent, + strhash(worktrees[i]->head_ref)); - hashmap_add(map, entry); + hashmap_add(map, &entry->ent); } } } @@ -1577,25 +1632,27 @@ static void lazy_init_worktree_map(void) if (ref_to_worktree_map.worktrees) return; - ref_to_worktree_map.worktrees = get_worktrees(0); + ref_to_worktree_map.worktrees = get_worktrees(); hashmap_init(&(ref_to_worktree_map.map), ref_to_worktree_map_cmpfnc, NULL, 0); populate_worktree_map(&(ref_to_worktree_map.map), ref_to_worktree_map.worktrees); } static char *get_worktree_path(const struct used_atom *atom, const struct ref_array_item *ref) { - struct hashmap_entry entry; + struct hashmap_entry entry, *e; struct ref_to_worktree_entry *lookup_result; lazy_init_worktree_map(); hashmap_entry_init(&entry, strhash(ref->refname)); - lookup_result = hashmap_get(&(ref_to_worktree_map.map), &entry, ref->refname); + e = hashmap_get(&(ref_to_worktree_map.map), &entry, ref->refname); - if (lookup_result) - return xstrdup(lookup_result->wt->path); - else + if (!e) return xstrdup(""); + + lookup_result = container_of(e, struct ref_to_worktree_entry, ent); + + return xstrdup(lookup_result->wt->path); } /* @@ -1695,7 +1752,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err) v->s = xstrdup(buf + 1); } continue; - } else if (!deref && grab_objectname(name, &ref->objectname, v, atom)) { + } else if (!deref && grab_oid(name, "objectname", &ref->objectname, v, atom)) { continue; } else if (!strcmp(name, "HEAD")) { if (atom->u.head && !strcmp(ref->refname, atom->u.head)) @@ -1766,7 +1823,7 @@ static int populate_value(struct ref_array_item *ref, struct strbuf *err) * If it is a tag object, see if we use a value that derefs * the object, and if we do grab the object it refers to. */ - oi_deref.oid = ((struct tag *)obj)->tagged->oid; + oi_deref.oid = *get_tagged_oid((struct tag *)obj); /* * NEEDSWORK: This derefs tag only once, which @@ -1910,15 +1967,15 @@ static void find_longest_prefixes_1(struct string_list *out, static void find_longest_prefixes(struct string_list *out, const char **patterns) { - struct argv_array sorted = ARGV_ARRAY_INIT; + struct strvec sorted = STRVEC_INIT; struct strbuf prefix = STRBUF_INIT; - argv_array_pushv(&sorted, patterns); - QSORT(sorted.argv, sorted.argc, qsort_strcmp); + strvec_pushv(&sorted, patterns); + QSORT(sorted.v, sorted.nr, qsort_strcmp); - find_longest_prefixes_1(out, &prefix, sorted.argv, sorted.argc); + find_longest_prefixes_1(out, &prefix, sorted.v, sorted.nr); - argv_array_clear(&sorted); + strvec_clear(&sorted); strbuf_release(&prefix); } @@ -1972,12 +2029,11 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter, } /* - * Given a ref (sha1, refname), check if the ref belongs to the array - * of sha1s. If the given ref is a tag, check if the given tag points - * at one of the sha1s in the given sha1 array. - * the given sha1_array. + * Given a ref (oid, refname), check if the ref belongs to the array + * of oids. If the given ref is a tag, check if the given tag points + * at one of the oids in the given oid array. * NEEDSWORK: - * 1. Only a single level of inderection is obtained, we might want to + * 1. Only a single level of indirection is obtained, we might want to * change this to account for multiple levels (e.g. annotated tags * pointing to annotated tags pointing to a commit.) * 2. As the refs are cached we might know what refname peels to without @@ -1997,7 +2053,7 @@ static const struct object_id *match_points_at(struct oid_array *points_at, if (!obj) die(_("malformed object at '%s'"), refname); if (obj->type == OBJ_TAG) - tagged_oid = &((struct tag *)obj)->tagged->oid; + tagged_oid = get_tagged_oid((struct tag *)obj); if (tagged_oid && oid_array_lookup(points_at, tagged_oid) >= 0) return tagged_oid; return NULL; @@ -2109,9 +2165,9 @@ static int ref_filter_handler(const char *refname, const struct object_id *oid, * obtain the commit using the 'oid' available and discard all * non-commits early. The actual filtering is done later. */ - if (filter->merge_commit || filter->with_commit || filter->no_commit || filter->verbose) { - commit = lookup_commit_reference_gently(the_repository, oid, - 1); + if (filter->reachable_from || filter->unreachable_from || + filter->with_commit || filter->no_commit || filter->verbose) { + commit = lookup_commit_reference_gently(the_repository, oid, 1); if (!commit) return 0; /* We perform the filtering for the '--contains' option... */ @@ -2166,19 +2222,28 @@ void ref_array_clear(struct ref_array *array) used_atom_cnt = 0; if (ref_to_worktree_map.worktrees) { - hashmap_free(&(ref_to_worktree_map.map), 1); + hashmap_free_entries(&(ref_to_worktree_map.map), + struct ref_to_worktree_entry, ent); free_worktrees(ref_to_worktree_map.worktrees); ref_to_worktree_map.worktrees = NULL; } } -static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata) +#define EXCLUDE_REACHED 0 +#define INCLUDE_REACHED 1 +static void reach_filter(struct ref_array *array, + struct commit_list *check_reachable, + int include_reached) { struct rev_info revs; int i, old_nr; - struct ref_filter *filter = ref_cbdata->filter; - struct ref_array *array = ref_cbdata->array; - struct commit **to_clear = xcalloc(sizeof(struct commit *), array->nr); + struct commit **to_clear; + struct commit_list *cr; + + if (!check_reachable) + return; + + to_clear = xcalloc(sizeof(struct commit *), array->nr); repo_init_revisions(the_repository, &revs, NULL); @@ -2188,8 +2253,11 @@ static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata) to_clear[i] = item->commit; } - filter->merge_commit->object.flags |= UNINTERESTING; - add_pending_object(&revs, &filter->merge_commit->object, ""); + for (cr = check_reachable; cr; cr = cr->next) { + struct commit *merge_commit = cr->item; + merge_commit->object.flags |= UNINTERESTING; + add_pending_object(&revs, &merge_commit->object, ""); + } revs.limited = 1; if (prepare_revision_walk(&revs)) @@ -2204,14 +2272,19 @@ static void do_merge_filter(struct ref_filter_cbdata *ref_cbdata) int is_merged = !!(commit->object.flags & UNINTERESTING); - if (is_merged == (filter->merge == REF_FILTER_MERGED_INCLUDE)) + if (is_merged == include_reached) array->items[array->nr++] = array->items[i]; else free_array_item(item); } clear_commit_marks_many(old_nr, to_clear, ALL_REV_FLAGS); - clear_commit_marks(filter->merge_commit, ALL_REV_FLAGS); + + while (check_reachable) { + struct commit *merge_commit = pop_commit(&check_reachable); + clear_commit_marks(merge_commit, ALL_REV_FLAGS); + } + free(to_clear); } @@ -2263,8 +2336,8 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int clear_contains_cache(&ref_cbdata.no_contains_cache); /* Filters that need revision walking */ - if (filter->merge_commit) - do_merge_filter(&ref_cbdata); + reach_filter(array, filter->reachable_from, INCLUDE_REACHED); + reach_filter(array, filter->unreachable_from, EXCLUDE_REACHED); return ret; } @@ -2291,7 +2364,7 @@ static int cmp_ref_sorting(struct ref_sorting *s, struct ref_array_item *a, stru if (va->value < vb->value) cmp = -1; else if (va->value == vb->value) - cmp = cmp_fn(a->refname, b->refname); + cmp = 0; else cmp = 1; } @@ -2310,7 +2383,16 @@ static int compare_refs(const void *a_, const void *b_, void *ref_sorting) if (cmp) return cmp; } - return 0; + s = ref_sorting; + return s && s->ignore_case ? + strcasecmp(a->refname, b->refname) : + strcmp(a->refname, b->refname); +} + +void ref_sorting_icase_all(struct ref_sorting *sorting, int flag) +{ + for (; sorting; sorting = sorting->next) + sorting->ignore_case = !!flag; } void ref_array_sort(struct ref_sorting *sorting, struct ref_array *array) @@ -2473,31 +2555,22 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset) { struct ref_filter *rf = opt->value; struct object_id oid; - int no_merged = starts_with(opt->long_name, "no"); + struct commit *merge_commit; BUG_ON_OPT_NEG(unset); - if (rf->merge) { - if (no_merged) { - return error(_("option `%s' is incompatible with --merged"), - opt->long_name); - } else { - return error(_("option `%s' is incompatible with --no-merged"), - opt->long_name); - } - } - - rf->merge = no_merged - ? REF_FILTER_MERGED_OMIT - : REF_FILTER_MERGED_INCLUDE; - if (get_oid(arg, &oid)) die(_("malformed object name %s"), arg); - rf->merge_commit = lookup_commit_reference_gently(the_repository, - &oid, 0); - if (!rf->merge_commit) + merge_commit = lookup_commit_reference_gently(the_repository, &oid, 0); + + if (!merge_commit) return error(_("option `%s' must point to a commit"), opt->long_name); + if (starts_with(opt->long_name, "no")) + commit_list_insert(merge_commit, &rf->unreachable_from); + else + commit_list_insert(merge_commit, &rf->reachable_from); + return 0; } |