Merge branch 'cc/bisect-filter'
[git.git] / refs.c
diff --git a/refs.c b/refs.c
index aeef257ee3cadfe751628f4157a4d63d77237090..9ccaf40172ee17472b4e33e9bd7f6dbac991d4bf 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -647,19 +647,24 @@ int for_each_ref(each_ref_fn fn, void *cb_data)
        return do_for_each_ref("refs/", fn, 0, 0, cb_data);
 }
 
+int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
+{
+       return do_for_each_ref(prefix, fn, strlen(prefix), 0, cb_data);
+}
+
 int for_each_tag_ref(each_ref_fn fn, void *cb_data)
 {
-       return do_for_each_ref("refs/tags/", fn, 10, 0, cb_data);
+       return for_each_ref_in("refs/tags/", fn, cb_data);
 }
 
 int for_each_branch_ref(each_ref_fn fn, void *cb_data)
 {
-       return do_for_each_ref("refs/heads/", fn, 11, 0, cb_data);
+       return for_each_ref_in("refs/heads/", fn, cb_data);
 }
 
 int for_each_remote_ref(each_ref_fn fn, void *cb_data)
 {
-       return do_for_each_ref("refs/remotes/", fn, 13, 0, cb_data);
+       return for_each_ref_in("refs/remotes/", fn, cb_data);
 }
 
 int for_each_rawref(each_ref_fn fn, void *cb_data)
@@ -676,6 +681,7 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
  * - it has double dots "..", or
  * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
  * - it ends with a "/".
+ * - it ends with ".lock"
  */
 
 static inline int bad_ref_char(int ch)
@@ -693,7 +699,7 @@ static inline int bad_ref_char(int ch)
 
 int check_ref_format(const char *ref)
 {
-       int ch, level, bad_type;
+       int ch, level, bad_type, last;
        int ret = CHECK_REF_FORMAT_OK;
        const char *cp = ref;
 
@@ -717,26 +723,43 @@ int check_ref_format(const char *ref)
                                return CHECK_REF_FORMAT_ERROR;
                }
 
+               last = ch;
                /* scan the rest of the path component */
                while ((ch = *cp++) != 0) {
                        bad_type = bad_ref_char(ch);
-                       if (bad_type) {
+                       if (bad_type)
                                return CHECK_REF_FORMAT_ERROR;
-                       }
                        if (ch == '/')
                                break;
-                       if (ch == '.' && *cp == '.')
+                       if (last == '.' && ch == '.')
+                               return CHECK_REF_FORMAT_ERROR;
+                       if (last == '@' && ch == '{')
                                return CHECK_REF_FORMAT_ERROR;
+                       last = ch;
                }
                level++;
                if (!ch) {
+                       if (ref <= cp - 2 && cp[-2] == '.')
+                               return CHECK_REF_FORMAT_ERROR;
                        if (level < 2)
                                return CHECK_REF_FORMAT_ONELEVEL;
+                       if (has_extension(ref, ".lock"))
+                               return CHECK_REF_FORMAT_ERROR;
                        return ret;
                }
        }
 }
 
+const char *prettify_ref(const struct ref *ref)
+{
+       const char *name = ref->name;
+       return name + (
+               !prefixcmp(name, "refs/heads/") ? 11 :
+               !prefixcmp(name, "refs/tags/") ? 10 :
+               !prefixcmp(name, "refs/remotes/") ? 13 :
+               0);
+}
+
 const char *ref_rev_parse_rules[] = {
        "%.*s",
        "refs/%.*s",