ref-filter: add option to filter out tags, branches and remotes
[gitweb.git] / sha1_name.c
index 46218ba02c6c1fd87cf51fa189843da3b7950dbe..da6874c15ec51964b6044ae96fc88c282decb0cc 100644 (file)
@@ -416,12 +416,12 @@ static int ambiguous_path(const char *path, int len)
        return slash;
 }
 
-static inline int upstream_mark(const char *string, int len)
+static inline int at_mark(const char *string, int len,
+                         const char **suffix, int nr)
 {
-       const char *suffix[] = { "@{upstream}", "@{u}" };
        int i;
 
-       for (i = 0; i < ARRAY_SIZE(suffix); i++) {
+       for (i = 0; i < nr; i++) {
                int suffix_len = strlen(suffix[i]);
                if (suffix_len <= len
                    && !memcmp(string, suffix[i], suffix_len))
@@ -430,6 +430,18 @@ static inline int upstream_mark(const char *string, int len)
        return 0;
 }
 
+static inline int upstream_mark(const char *string, int len)
+{
+       const char *suffix[] = { "@{upstream}", "@{u}" };
+       return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
+}
+
+static inline int push_mark(const char *string, int len)
+{
+       const char *suffix[] = { "@{push}" };
+       return at_mark(string, len, suffix, ARRAY_SIZE(suffix));
+}
+
 static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags);
 static int interpret_nth_prior_checkout(const char *name, int namelen, struct strbuf *buf);
 
@@ -477,7 +489,8 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1,
                                        nth_prior = 1;
                                        continue;
                                }
-                               if (!upstream_mark(str + at, len - at)) {
+                               if (!upstream_mark(str + at, len - at) &&
+                                   !push_mark(str + at, len - at)) {
                                        reflog_len = (len-1) - (at+2);
                                        len = at;
                                }
@@ -563,7 +576,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1,
                                if (!(flags & GET_SHA1_QUIETLY)) {
                                        warning("Log for '%.*s' only goes "
                                                "back to %s.", len, str,
-                                               show_date(co_time, co_tz, DATE_RFC2822));
+                                               show_date(co_time, co_tz, DATE_MODE(RFC2822)));
                                }
                        } else {
                                if (flags & GET_SHA1_QUIETLY) {
@@ -832,11 +845,11 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned l
 /* Remember to update object flag allocation in object.h */
 #define ONELINE_SEEN (1u<<20)
 
-static int handle_one_ref(const char *path,
-               const unsigned char *sha1, int flag, void *cb_data)
+static int handle_one_ref(const char *path, const struct object_id *oid,
+                         int flag, void *cb_data)
 {
        struct commit_list **list = cb_data;
-       struct object *object = parse_object(sha1);
+       struct object *object = parse_object(oid->hash);
        if (!object)
                return 0;
        if (object->type == OBJ_TAG) {
@@ -1056,46 +1069,36 @@ static void set_shortened_ref(struct strbuf *buf, const char *ref)
        free(s);
 }
 
-static const char *get_upstream_branch(const char *branch_buf, int len)
-{
-       char *branch = xstrndup(branch_buf, len);
-       struct branch *upstream = branch_get(*branch ? branch : NULL);
-
-       /*
-        * Upstream can be NULL only if branch refers to HEAD and HEAD
-        * points to something different than a branch.
-        */
-       if (!upstream)
-               die(_("HEAD does not point to a branch"));
-       if (!upstream->merge || !upstream->merge[0]->dst) {
-               if (!ref_exists(upstream->refname))
-                       die(_("No such branch: '%s'"), branch);
-               if (!upstream->merge) {
-                       die(_("No upstream configured for branch '%s'"),
-                               upstream->name);
-               }
-               die(
-                       _("Upstream branch '%s' not stored as a remote-tracking branch"),
-                       upstream->merge[0]->src);
-       }
-       free(branch);
-
-       return upstream->merge[0]->dst;
-}
-
-static int interpret_upstream_mark(const char *name, int namelen,
-                                  int at, struct strbuf *buf)
+static int interpret_branch_mark(const char *name, int namelen,
+                                int at, struct strbuf *buf,
+                                int (*get_mark)(const char *, int),
+                                const char *(*get_data)(struct branch *,
+                                                        struct strbuf *))
 {
        int len;
+       struct branch *branch;
+       struct strbuf err = STRBUF_INIT;
+       const char *value;
 
-       len = upstream_mark(name + at, namelen - at);
+       len = get_mark(name + at, namelen - at);
        if (!len)
                return -1;
 
        if (memchr(name, ':', at))
                return -1;
 
-       set_shortened_ref(buf, get_upstream_branch(name, at));
+       if (at) {
+               char *name_str = xmemdupz(name, at);
+               branch = branch_get(name_str);
+               free(name_str);
+       } else
+               branch = branch_get(NULL);
+
+       value = get_data(branch, &err);
+       if (!value)
+               die("%s", err.buf);
+
+       set_shortened_ref(buf, value);
        return len + at;
 }
 
@@ -1146,7 +1149,13 @@ int interpret_branch_name(const char *name, int namelen, struct strbuf *buf)
                if (len > 0)
                        return reinterpret(name, namelen, len, buf);
 
-               len = interpret_upstream_mark(name, namelen, at - name, buf);
+               len = interpret_branch_mark(name, namelen, at - name, buf,
+                                           upstream_mark, branch_get_upstream);
+               if (len > 0)
+                       return len;
+
+               len = interpret_branch_mark(name, namelen, at - name, buf,
+                                           push_mark, branch_get_push);
                if (len > 0)
                        return len;
        }
@@ -1370,6 +1379,7 @@ static int get_sha1_with_context_1(const char *name,
                int pos;
                if (!only_to_die && namelen > 2 && name[1] == '/') {
                        struct commit_list *list = NULL;
+
                        for_each_ref(handle_one_ref, &list);
                        commit_list_sort_by_date(&list);
                        return get_sha1_oneline(name + 2, sha1, list);