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)