Refactor check_refname_format()

Among other things, extract a function check_refname_component(). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Sep 15, 2011 at 23:10 UTC 49295d4e3fb58c6179b7434cd87805f86cb1f7b7
1 file changed +55 -40
refs.c
+55 -40
@@ -872,55 +872,70 @@ static inline int bad_ref_char(int ch)
872 return 0;
873 }
874
875 +/*
876 + * Try to read one refname component from the front of ref. Return
877 + * the length of the component found, or -1 if the component is not
878 + * legal.
879 + */
880 +static int check_refname_component(const char *ref)
881 +{
882 + const char *cp;
883 + char last = '\0';
884 +
885 + for (cp = ref; ; cp++) {
886 + char ch = *cp;
887 + if (ch == '\0' || ch == '/')
888 + break;
889 + if (bad_ref_char(ch))
890 + return -1; /* Illegal character in refname. */
891 + if (last == '.' && ch == '.')
892 + return -1; /* Refname contains "..". */
893 + if (last == '@' && ch == '{')
894 + return -1; /* Refname contains "@{". */
895 + last = ch;
896 + }
897 + if (cp == ref)
898 + return -1; /* Component has zero length. */
899 + if (ref[0] == '.')
900 + return -1; /* Component starts with '.'. */
901 + return cp - ref;
902 +}
903 +
904 int check_refname_format(const char *ref, int flags)
905 {
877 - int ch, level, last;
878 - const char *cp = ref;
906 + int component_len, component_count = 0;
907
880 - level = 0;
908 while (1) {
882 - while ((ch = *cp++) == '/')
883 - ; /* tolerate duplicated slashes */
884 - if (!ch)
885 - /* should not end with slashes */
886 - return -1;
887 -
888 - /* we are at the beginning of the path component */
889 - if (ch == '.')
890 - return -1;
891 - if (bad_ref_char(ch)) {
892 - if ((flags & REFNAME_REFSPEC_PATTERN) && ch == '*' &&
893 - (!*cp || *cp == '/'))
909 + while (*ref == '/')
910 + ref++; /* tolerate leading and repeated slashes */
911 +
912 + /* We are at the start of a path component. */
913 + component_len = check_refname_component(ref);
914 + if (component_len < 0) {
915 + if ((flags & REFNAME_REFSPEC_PATTERN) &&
916 + ref[0] == '*' &&
917 + (ref[1] == '\0' || ref[1] == '/')) {
918 /* Accept one wildcard as a full refname component. */
919 flags &= ~REFNAME_REFSPEC_PATTERN;
896 - else
897 - return -1;
898 - }
899 -
900 - last = ch;
901 - /* scan the rest of the path component */
902 - while ((ch = *cp++) != 0) {
903 - if (bad_ref_char(ch))
904 - return -1;
905 - if (ch == '/')
906 - break;
907 - if (last == '.' && ch == '.')
908 - return -1;
909 - if (last == '@' && ch == '{')
910 - return -1;
911 - last = ch;
912 - }
913 - level++;
914 - if (!ch) {
915 - if (ref <= cp - 2 && cp[-2] == '.')
916 - return -1;
917 - if (level < 2 && !(flags & REFNAME_ALLOW_ONELEVEL))
918 - return -1;
919 - if (has_extension(ref, ".lock"))
920 + component_len = 1;
921 + } else {
922 return -1;
921 - return 0;
923 + }
924 }
925 + component_count++;
926 + if (ref[component_len] == '\0')
927 + break;
928 + /* Skip to next component. */
929 + ref += component_len + 1;
930 }
931 +
932 + if (ref[component_len - 1] == '.')
933 + return -1; /* Refname ends with '.'. */
934 + if (component_len >= 5 && !memcmp(&ref[component_len - 5], ".lock", 5))
935 + return -1; /* Refname ends with ".lock". */
936 + if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
937 + return -1; /* Refname has only one component. */
938 + return 0;
939 }
940
941 const char *prettify_refname(const char *name)