ref-filter: add option to filter out tags, branches and remotes
[gitweb.git] / sha1_name.c
index 6de8c87c8a120186eef41eb63c724a6e1a80e0c6..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);
@@ -1433,11 +1443,19 @@ static int get_sha1_with_context_1(const char *name,
                        new_filename = resolve_relative_path(filename);
                        if (new_filename)
                                filename = new_filename;
-                       ret = get_tree_entry(tree_sha1, filename, sha1, &oc->mode);
-                       if (ret && only_to_die) {
-                               diagnose_invalid_sha1_path(prefix, filename,
-                                                          tree_sha1,
-                                                          name, len);
+                       if (flags & GET_SHA1_FOLLOW_SYMLINKS) {
+                               ret = get_tree_entry_follow_symlinks(tree_sha1,
+                                       filename, sha1, &oc->symlink_path,
+                                       &oc->mode);
+                       } else {
+                               ret = get_tree_entry(tree_sha1, filename,
+                                                    sha1, &oc->mode);
+                               if (ret && only_to_die) {
+                                       diagnose_invalid_sha1_path(prefix,
+                                                                  filename,
+                                                                  tree_sha1,
+                                                                  name, len);
+                               }
                        }
                        hashcpy(oc->tree, tree_sha1);
                        strlcpy(oc->path, filename, sizeof(oc->path));
@@ -1468,5 +1486,7 @@ void maybe_die_on_misspelt_object_name(const char *name, const char *prefix)
 
 int get_sha1_with_context(const char *str, unsigned flags, unsigned char *sha1, struct object_context *orc)
 {
+       if (flags & GET_SHA1_FOLLOW_SYMLINKS && flags & GET_SHA1_ONLY_TO_DIE)
+               die("BUG: incompatible flags for get_sha1_with_context");
        return get_sha1_with_context_1(str, flags, NULL, sha1, orc);
 }