t0302 & t3900: add forgotten quotes
[gitweb.git] / ref-filter.c
index 4ee7ebcda310a03d19c1bbfd13336b587c356fc3..467c0279c9b6370b57080b5f1fcf20bdfd7e451e 100644 (file)
@@ -93,6 +93,7 @@ static struct used_atom {
                        unsigned int length;
                } objectname;
                struct refname_atom refname;
+               char *head;
        } u;
 } *used_atom;
 static int used_atom_cnt, need_tagged, need_symref;
@@ -220,7 +221,7 @@ static void objectname_atom_parser(struct used_atom *atom, const char *arg)
 
 static void refname_atom_parser(struct used_atom *atom, const char *arg)
 {
-       return refname_atom_parser_internal(&atom->u.refname, arg, atom->name);
+       refname_atom_parser_internal(&atom->u.refname, arg, atom->name);
 }
 
 static align_type parse_align_position(const char *s)
@@ -287,6 +288,12 @@ static void if_atom_parser(struct used_atom *atom, const char *arg)
        }
 }
 
+static void head_atom_parser(struct used_atom *atom, const char *arg)
+{
+       unsigned char unused[GIT_SHA1_RAWSZ];
+
+       atom->u.head = resolve_refdup("HEAD", RESOLVE_REF_READING, unused, NULL);
+}
 
 static struct {
        const char *name;
@@ -325,7 +332,7 @@ static struct {
        { "push", FIELD_STR, remote_ref_atom_parser },
        { "symref", FIELD_STR, refname_atom_parser },
        { "flag" },
-       { "HEAD" },
+       { "HEAD", FIELD_STR, head_atom_parser },
        { "color", FIELD_STR, color_atom_parser },
        { "align", FIELD_STR, align_atom_parser },
        { "end" },
@@ -1251,13 +1258,17 @@ char *get_head_description(void)
                            state.branch);
        else if (state.detached_from) {
                if (state.detached_at)
-                       /* TRANSLATORS: make sure this matches
-                          "HEAD detached at " in wt-status.c */
+                       /*
+                        * TRANSLATORS: make sure this matches "HEAD
+                        * detached at " in wt-status.c
+                        */
                        strbuf_addf(&desc, _("(HEAD detached at %s)"),
                                state.detached_from);
                else
-                       /* TRANSLATORS: make sure this matches
-                          "HEAD detached from " in wt-status.c */
+                       /*
+                        * TRANSLATORS: make sure this matches "HEAD
+                        * detached from " in wt-status.c
+                        */
                        strbuf_addf(&desc, _("(HEAD detached from %s)"),
                                state.detached_from);
        }
@@ -1369,12 +1380,7 @@ static void populate_value(struct ref_array_item *ref)
                } else if (!deref && grab_objectname(name, ref->objectname, v, atom)) {
                        continue;
                } else if (!strcmp(name, "HEAD")) {
-                       const char *head;
-                       unsigned char sha1[20];
-
-                       head = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
-                                                 sha1, NULL);
-                       if (head && !strcmp(ref->refname, head))
+                       if (atom->u.head && !strcmp(ref->refname, atom->u.head))
                                v->s = "*";
                        else
                                v->s = " ";
@@ -1487,6 +1493,7 @@ struct ref_filter_cbdata {
        struct ref_array *array;
        struct ref_filter *filter;
        struct contains_cache contains_cache;
+       struct contains_cache no_contains_cache;
 };
 
 /*
@@ -1586,11 +1593,11 @@ static enum contains_result contains_tag_algo(struct commit *candidate,
 }
 
 static int commit_contains(struct ref_filter *filter, struct commit *commit,
-                          struct contains_cache *cache)
+                          struct commit_list *list, struct contains_cache *cache)
 {
        if (filter->with_commit_tag_algo)
-               return contains_tag_algo(commit, filter->with_commit, cache) == CONTAINS_YES;
-       return is_descendant_of(commit, filter->with_commit);
+               return contains_tag_algo(commit, list, cache) == CONTAINS_YES;
+       return is_descendant_of(commit, list);
 }
 
 /*
@@ -1677,21 +1684,21 @@ static int filter_pattern_match(struct ref_filter *filter, const char *refname)
  * the need to parse the object via parse_object(). peel_ref() might be a
  * more efficient alternative to obtain the pointee.
  */
-static const struct object_id *match_points_at(struct sha1_array *points_at,
+static const struct object_id *match_points_at(struct oid_array *points_at,
                                               const struct object_id *oid,
                                               const char *refname)
 {
        const struct object_id *tagged_oid = NULL;
        struct object *obj;
 
-       if (sha1_array_lookup(points_at, oid) >= 0)
+       if (oid_array_lookup(points_at, oid) >= 0)
                return oid;
        obj = parse_object(oid->hash);
        if (!obj)
                die(_("malformed object at '%s'"), refname);
        if (obj->type == OBJ_TAG)
                tagged_oid = &((struct tag *)obj)->tagged->oid;
-       if (tagged_oid && sha1_array_lookup(points_at, tagged_oid) >= 0)
+       if (tagged_oid && oid_array_lookup(points_at, tagged_oid) >= 0)
                return tagged_oid;
        return NULL;
 }
@@ -1780,13 +1787,17 @@ 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->verbose) {
+       if (filter->merge_commit || filter->with_commit || filter->no_commit || filter->verbose) {
                commit = lookup_commit_reference_gently(oid->hash, 1);
                if (!commit)
                        return 0;
-               /* We perform the filtering for the '--contains' option */
+               /* We perform the filtering for the '--contains' option... */
                if (filter->with_commit &&
-                   !commit_contains(filter, commit, &ref_cbdata->contains_cache))
+                   !commit_contains(filter, commit, filter->with_commit, &ref_cbdata->contains_cache))
+                       return 0;
+               /* ...or for the `--no-contains' option */
+               if (filter->no_commit &&
+                   commit_contains(filter, commit, filter->no_commit, &ref_cbdata->no_contains_cache))
                        return 0;
        }
 
@@ -1887,6 +1898,7 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
        filter->kind = type & FILTER_REFS_KIND_MASK;
 
        init_contains_cache(&ref_cbdata.contains_cache);
+       init_contains_cache(&ref_cbdata.no_contains_cache);
 
        /*  Simple per-ref filtering */
        if (!filter->kind)
@@ -1911,6 +1923,7 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
        }
 
        clear_contains_cache(&ref_cbdata.contains_cache);
+       clear_contains_cache(&ref_cbdata.no_contains_cache);
 
        /*  Filters that need revision walking */
        if (filter->merge_commit)
@@ -2084,8 +2097,17 @@ int parse_opt_merge_filter(const struct option *opt, const char *arg, int unset)
 {
        struct ref_filter *rf = opt->value;
        unsigned char sha1[20];
+       int no_merged = starts_with(opt->long_name, "no");
+
+       if (rf->merge) {
+               if (no_merged) {
+                       return opterror(opt, "is incompatible with --merged", 0);
+               } else {
+                       return opterror(opt, "is incompatible with --no-merged", 0);
+               }
+       }
 
-       rf->merge = starts_with(opt->long_name, "no")
+       rf->merge = no_merged
                ? REF_FILTER_MERGED_OMIT
                : REF_FILTER_MERGED_INCLUDE;