refs.c: reorder definitions more logically

Reorder definitions in file: first check_refname_format() and helper functions, then the functions for managing the ref_entry and ref_array data structures, then ref_cache, then the more "business-logicky" stuff. No code is changed. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Apr 10, 2012 at 07:30 UTC bc5fd6d3c29f1a734ebd202573b39c1f66c41744
1 file changed +256 -253
refs.c
+256 -253
@@ -4,16 +4,102 @@
4 #include "tag.h"
5 #include "dir.h"
6
7 -/* ISSYMREF=0x01, ISPACKED=0x02 and ISBROKEN=0x04 are public interfaces */
8 -#define REF_KNOWS_PEELED 0x10
7 +/*
8 + * Make sure "ref" is something reasonable to have under ".git/refs/";
9 + * We do not like it if:
10 + *
11 + * - any path component of it begins with ".", or
12 + * - it has double dots "..", or
13 + * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
14 + * - it ends with a "/".
15 + * - it ends with ".lock"
16 + * - it contains a "\" (backslash)
17 + */
18
10 -struct ref_entry {
11 - unsigned char flag; /* ISSYMREF? ISPACKED? */
12 - unsigned char sha1[20];
13 - unsigned char peeled[20];
14 - /* The full name of the reference (e.g., "refs/heads/master"): */
15 - char name[FLEX_ARRAY];
16 -};
19 +/* Return true iff ch is not allowed in reference names. */
20 +static inline int bad_ref_char(int ch)
21 +{
22 + if (((unsigned) ch) <= ' ' || ch == 0x7f ||
23 + ch == '~' || ch == '^' || ch == ':' || ch == '\\')
24 + return 1;
25 + /* 2.13 Pattern Matching Notation */
26 + if (ch == '*' || ch == '?' || ch == '[') /* Unsupported */
27 + return 1;
28 + return 0;
29 +}
30 +
31 +/*
32 + * Try to read one refname component from the front of refname. Return
33 + * the length of the component found, or -1 if the component is not
34 + * legal.
35 + */
36 +static int check_refname_component(const char *refname, int flags)
37 +{
38 + const char *cp;
39 + char last = '\0';
40 +
41 + for (cp = refname; ; cp++) {
42 + char ch = *cp;
43 + if (ch == '\0' || ch == '/')
44 + break;
45 + if (bad_ref_char(ch))
46 + return -1; /* Illegal character in refname. */
47 + if (last == '.' && ch == '.')
48 + return -1; /* Refname contains "..". */
49 + if (last == '@' && ch == '{')
50 + return -1; /* Refname contains "@{". */
51 + last = ch;
52 + }
53 + if (cp == refname)
54 + return -1; /* Component has zero length. */
55 + if (refname[0] == '.') {
56 + if (!(flags & REFNAME_DOT_COMPONENT))
57 + return -1; /* Component starts with '.'. */
58 + /*
59 + * Even if leading dots are allowed, don't allow "."
60 + * as a component (".." is prevented by a rule above).
61 + */
62 + if (refname[1] == '\0')
63 + return -1; /* Component equals ".". */
64 + }
65 + if (cp - refname >= 5 && !memcmp(cp - 5, ".lock", 5))
66 + return -1; /* Refname ends with ".lock". */
67 + return cp - refname;
68 +}
69 +
70 +int check_refname_format(const char *refname, int flags)
71 +{
72 + int component_len, component_count = 0;
73 +
74 + while (1) {
75 + /* We are at the start of a path component. */
76 + component_len = check_refname_component(refname, flags);
77 + if (component_len < 0) {
78 + if ((flags & REFNAME_REFSPEC_PATTERN) &&
79 + refname[0] == '*' &&
80 + (refname[1] == '\0' || refname[1] == '/')) {
81 + /* Accept one wildcard as a full refname component. */
82 + flags &= ~REFNAME_REFSPEC_PATTERN;
83 + component_len = 1;
84 + } else {
85 + return -1;
86 + }
87 + }
88 + component_count++;
89 + if (refname[component_len] == '\0')
90 + break;
91 + /* Skip to next component. */
92 + refname += component_len + 1;
93 + }
94 +
95 + if (refname[component_len - 1] == '.')
96 + return -1; /* Refname ends with '.'. */
97 + if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
98 + return -1; /* Refname has only one component. */
99 + return 0;
100 +}
101 +
102 +struct ref_entry;
103
104 struct ref_array {
105 int nr, alloc;
@@ -29,38 +115,16 @@ struct ref_array {
115 struct ref_entry **refs;
116 };
117
32 -/*
33 - * Parse one line from a packed-refs file. Write the SHA1 to sha1.
34 - * Return a pointer to the refname within the line (null-terminated),
35 - * or NULL if there was a problem.
36 - */
37 -static const char *parse_ref_line(char *line, unsigned char *sha1)
38 -{
39 - /*
40 - * 42: the answer to everything.
41 - *
42 - * In this case, it happens to be the answer to
43 - * 40 (length of sha1 hex representation)
44 - * +1 (space in between hex and name)
45 - * +1 (newline at the end of the line)
46 - */
47 - int len = strlen(line) - 42;
48 -
49 - if (len <= 0)
50 - return NULL;
51 - if (get_sha1_hex(line, sha1) < 0)
52 - return NULL;
53 - if (!isspace(line[40]))
54 - return NULL;
55 - line += 41;
56 - if (isspace(*line))
57 - return NULL;
58 - if (line[len] != '\n')
59 - return NULL;
60 - line[len] = 0;
118 +/* ISSYMREF=0x01, ISPACKED=0x02 and ISBROKEN=0x04 are public interfaces */
119 +#define REF_KNOWS_PEELED 0x10
120
62 - return line;
63 -}
121 +struct ref_entry {
122 + unsigned char flag; /* ISSYMREF? ISPACKED? */
123 + unsigned char sha1[20];
124 + unsigned char peeled[20];
125 + /* The full name of the reference (e.g., "refs/heads/master"): */
126 + char name[FLEX_ARRAY];
127 +};
128
129 static struct ref_entry *create_ref_entry(const char *refname,
130 const unsigned char *sha1, int flag,
@@ -88,6 +152,16 @@ static void add_ref(struct ref_array *refs, struct ref_entry *ref)
152 refs->refs[refs->nr++] = ref;
153 }
154
155 +static void clear_ref_array(struct ref_array *array)
156 +{
157 + int i;
158 + for (i = 0; i < array->nr; i++)
159 + free(array->refs[i]);
160 + free(array->refs);
161 + array->sorted = array->nr = array->alloc = 0;
162 + array->refs = NULL;
163 +}
164 +
165 static int ref_entry_cmp(const void *a, const void *b)
166 {
167 struct ref_entry *one = *(struct ref_entry **)a;
@@ -95,6 +169,33 @@ static int ref_entry_cmp(const void *a, const void *b)
169 return strcmp(one->name, two->name);
170 }
171
172 +static void sort_ref_array(struct ref_array *array);
173 +
174 +static struct ref_entry *search_ref_array(struct ref_array *array, const char *refname)
175 +{
176 + struct ref_entry *e, **r;
177 + int len;
178 +
179 + if (refname == NULL)
180 + return NULL;
181 +
182 + if (!array->nr)
183 + return NULL;
184 + sort_ref_array(array);
185 + len = strlen(refname) + 1;
186 + e = xmalloc(sizeof(struct ref_entry) + len);
187 + memcpy(e->name, refname, len);
188 +
189 + r = bsearch(&e, array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
190 +
191 + free(e);
192 +
193 + if (r == NULL)
194 + return NULL;
195 +
196 + return *r;
197 +}
198 +
199 /*
200 * Emit a warning and return true iff ref1 and ref2 have the same name
201 * and the same sha1. Die if they have the same name but different
@@ -142,29 +243,55 @@ static void sort_ref_array(struct ref_array *array)
243 array->sorted = array->nr = i + 1;
244 }
245
145 -static struct ref_entry *search_ref_array(struct ref_array *array, const char *refname)
146 -{
147 - struct ref_entry *e, **r;
148 - int len;
149 -
150 - if (refname == NULL)
151 - return NULL;
152 -
153 - if (!array->nr)
154 - return NULL;
155 - sort_ref_array(array);
156 - len = strlen(refname) + 1;
157 - e = xmalloc(sizeof(struct ref_entry) + len);
158 - memcpy(e->name, refname, len);
246 +#define DO_FOR_EACH_INCLUDE_BROKEN 01
247
160 - r = bsearch(&e, array->refs, array->nr, sizeof(*array->refs), ref_entry_cmp);
248 +static struct ref_entry *current_ref;
249
162 - free(e);
250 +static int do_one_ref(const char *base, each_ref_fn fn, int trim,
251 + int flags, void *cb_data, struct ref_entry *entry)
252 +{
253 + if (prefixcmp(entry->name, base))
254 + return 0;
255
164 - if (r == NULL)
165 - return NULL;
256 + if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
257 + if (entry->flag & REF_ISBROKEN)
258 + return 0; /* ignore broken refs e.g. dangling symref */
259 + if (!has_sha1_file(entry->sha1)) {
260 + error("%s does not point to a valid object!", entry->name);
261 + return 0;
262 + }
263 + }
264 + current_ref = entry;
265 + return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
266 +}
267
167 - return *r;
268 +/*
269 + * Return true iff a reference named refname could be created without
270 + * conflicting with the name of an existing reference. If oldrefname
271 + * is non-NULL, ignore potential conflicts with oldrefname (e.g.,
272 + * because oldrefname is scheduled for deletion in the same
273 + * operation).
274 + */
275 +static int is_refname_available(const char *refname, const char *oldrefname,
276 + struct ref_array *array)
277 +{
278 + int i, namlen = strlen(refname); /* e.g. 'foo/bar' */
279 + for (i = 0; i < array->nr; i++) {
280 + struct ref_entry *entry = array->refs[i];
281 + /* entry->name could be 'foo' or 'foo/bar/baz' */
282 + if (!oldrefname || strcmp(oldrefname, entry->name)) {
283 + int len = strlen(entry->name);
284 + int cmplen = (namlen < len) ? namlen : len;
285 + const char *lead = (namlen < len) ? entry->name : refname;
286 + if (!strncmp(refname, entry->name, cmplen) &&
287 + lead[cmplen] == '/') {
288 + error("'%s' exists; cannot create '%s'",
289 + entry->name, refname);
290 + return 0;
291 + }
292 + }
293 + }
294 + return 1;
295 }
296
297 /*
@@ -181,18 +308,6 @@ static struct ref_cache {
308 char name[FLEX_ARRAY];
309 } *ref_cache;
310
184 -static struct ref_entry *current_ref;
185 -
186 -static void clear_ref_array(struct ref_array *array)
187 -{
188 - int i;
189 - for (i = 0; i < array->nr; i++)
190 - free(array->refs[i]);
191 - free(array->refs);
192 - array->sorted = array->nr = array->alloc = 0;
193 - array->refs = NULL;
194 -}
195 -
311 static void clear_packed_ref_cache(struct ref_cache *refs)
312 {
313 if (refs->did_packed)
@@ -249,6 +364,39 @@ void invalidate_ref_cache(const char *submodule)
364 clear_loose_ref_cache(refs);
365 }
366
367 +/*
368 + * Parse one line from a packed-refs file. Write the SHA1 to sha1.
369 + * Return a pointer to the refname within the line (null-terminated),
370 + * or NULL if there was a problem.
371 + */
372 +static const char *parse_ref_line(char *line, unsigned char *sha1)
373 +{
374 + /*
375 + * 42: the answer to everything.
376 + *
377 + * In this case, it happens to be the answer to
378 + * 40 (length of sha1 hex representation)
379 + * +1 (space in between hex and name)
380 + * +1 (newline at the end of the line)
381 + */
382 + int len = strlen(line) - 42;
383 +
384 + if (len <= 0)
385 + return NULL;
386 + if (get_sha1_hex(line, sha1) < 0)
387 + return NULL;
388 + if (!isspace(line[40]))
389 + return NULL;
390 + line += 41;
391 + if (isspace(*line))
392 + return NULL;
393 + if (line[len] != '\n')
394 + return NULL;
395 + line[len] = 0;
396 +
397 + return line;
398 +}
399 +
400 static void read_packed_refs(FILE *f, struct ref_array *array)
401 {
402 struct ref_entry *last = NULL;
@@ -320,7 +468,6 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
468 else
469 path = git_path("%s", base);
470
323 -
471 dir = opendir(path);
472
473 if (dir) {
@@ -374,40 +521,6 @@ static void get_ref_dir(struct ref_cache *refs, const char *base,
521 }
522 }
523
377 -struct warn_if_dangling_data {
378 - FILE *fp;
379 - const char *refname;
380 - const char *msg_fmt;
381 -};
382 -
383 -static int warn_if_dangling_symref(const char *refname, const unsigned char *sha1,
384 - int flags, void *cb_data)
385 -{
386 - struct warn_if_dangling_data *d = cb_data;
387 - const char *resolves_to;
388 - unsigned char junk[20];
389 -
390 - if (!(flags & REF_ISSYMREF))
391 - return 0;
392 -
393 - resolves_to = resolve_ref_unsafe(refname, junk, 0, NULL);
394 - if (!resolves_to || strcmp(resolves_to, d->refname))
395 - return 0;
396 -
397 - fprintf(d->fp, d->msg_fmt, refname);
398 - return 0;
399 -}
400 -
401 -void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
402 -{
403 - struct warn_if_dangling_data data;
404 -
405 - data.fp = fp;
406 - data.refname = refname;
407 - data.msg_fmt = msg_fmt;
408 - for_each_rawref(warn_if_dangling_symref, &data);
409 -}
410 -
524 static struct ref_array *get_loose_refs(struct ref_cache *refs)
525 {
526 if (!refs->did_loose) {
@@ -645,23 +758,10 @@ int read_ref(const char *refname, unsigned char *sha1)
758 return read_ref_full(refname, sha1, 1, NULL);
759 }
760
648 -#define DO_FOR_EACH_INCLUDE_BROKEN 01
649 -static int do_one_ref(const char *base, each_ref_fn fn, int trim,
650 - int flags, void *cb_data, struct ref_entry *entry)
761 +int ref_exists(const char *refname)
762 {
652 - if (prefixcmp(entry->name, base))
653 - return 0;
654 -
655 - if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
656 - if (entry->flag & REF_ISBROKEN)
657 - return 0; /* ignore broken refs e.g. dangling symref */
658 - if (!has_sha1_file(entry->sha1)) {
659 - error("%s does not point to a valid object!", entry->name);
660 - return 0;
661 - }
662 - }
663 - current_ref = entry;
664 - return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
763 + unsigned char sha1[20];
764 + return !!resolve_ref_unsafe(refname, sha1, 1, NULL);
765 }
766
767 static int filter_refs(const char *refname, const unsigned char *sha1, int flags,
@@ -714,6 +814,40 @@ fallback:
814 return -1;
815 }
816
817 +struct warn_if_dangling_data {
818 + FILE *fp;
819 + const char *refname;
820 + const char *msg_fmt;
821 +};
822 +
823 +static int warn_if_dangling_symref(const char *refname, const unsigned char *sha1,
824 + int flags, void *cb_data)
825 +{
826 + struct warn_if_dangling_data *d = cb_data;
827 + const char *resolves_to;
828 + unsigned char junk[20];
829 +
830 + if (!(flags & REF_ISSYMREF))
831 + return 0;
832 +
833 + resolves_to = resolve_ref_unsafe(refname, junk, 0, NULL);
834 + if (!resolves_to || strcmp(resolves_to, d->refname))
835 + return 0;
836 +
837 + fprintf(d->fp, d->msg_fmt, refname);
838 + return 0;
839 +}
840 +
841 +void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname)
842 +{
843 + struct warn_if_dangling_data data;
844 +
845 + data.fp = fp;
846 + data.refname = refname;
847 + data.msg_fmt = msg_fmt;
848 + for_each_rawref(warn_if_dangling_symref, &data);
849 +}
850 +
851 static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,
852 int trim, int flags, void *cb_data)
853 {
@@ -757,7 +891,6 @@ end_each:
891 return retval;
892 }
893
760 -
894 static int do_head_ref(const char *submodule, each_ref_fn fn, void *cb_data)
895 {
896 unsigned char sha1[20];
@@ -908,101 +1041,6 @@ int for_each_rawref(each_ref_fn fn, void *cb_data)
1041 DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
1042 }
1043
911 -/*
912 - * Make sure "ref" is something reasonable to have under ".git/refs/";
913 - * We do not like it if:
914 - *
915 - * - any path component of it begins with ".", or
916 - * - it has double dots "..", or
917 - * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
918 - * - it ends with a "/".
919 - * - it ends with ".lock"
920 - * - it contains a "\" (backslash)
921 - */
922 -
923 -/* Return true iff ch is not allowed in reference names. */
924 -static inline int bad_ref_char(int ch)
925 -{
926 - if (((unsigned) ch) <= ' ' || ch == 0x7f ||
927 - ch == '~' || ch == '^' || ch == ':' || ch == '\\')
928 - return 1;
929 - /* 2.13 Pattern Matching Notation */
930 - if (ch == '*' || ch == '?' || ch == '[') /* Unsupported */
931 - return 1;
932 - return 0;
933 -}
934 -
935 -/*
936 - * Try to read one refname component from the front of refname. Return
937 - * the length of the component found, or -1 if the component is not
938 - * legal.
939 - */
940 -static int check_refname_component(const char *refname, int flags)
941 -{
942 - const char *cp;
943 - char last = '\0';
944 -
945 - for (cp = refname; ; cp++) {
946 - char ch = *cp;
947 - if (ch == '\0' || ch == '/')
948 - break;
949 - if (bad_ref_char(ch))
950 - return -1; /* Illegal character in refname. */
951 - if (last == '.' && ch == '.')
952 - return -1; /* Refname contains "..". */
953 - if (last == '@' && ch == '{')
954 - return -1; /* Refname contains "@{". */
955 - last = ch;
956 - }
957 - if (cp == refname)
958 - return -1; /* Component has zero length. */
959 - if (refname[0] == '.') {
960 - if (!(flags & REFNAME_DOT_COMPONENT))
961 - return -1; /* Component starts with '.'. */
962 - /*
963 - * Even if leading dots are allowed, don't allow "."
964 - * as a component (".." is prevented by a rule above).
965 - */
966 - if (refname[1] == '\0')
967 - return -1; /* Component equals ".". */
968 - }
969 - if (cp - refname >= 5 && !memcmp(cp - 5, ".lock", 5))
970 - return -1; /* Refname ends with ".lock". */
971 - return cp - refname;
972 -}
973 -
974 -int check_refname_format(const char *refname, int flags)
975 -{
976 - int component_len, component_count = 0;
977 -
978 - while (1) {
979 - /* We are at the start of a path component. */
980 - component_len = check_refname_component(refname, flags);
981 - if (component_len < 0) {
982 - if ((flags & REFNAME_REFSPEC_PATTERN) &&
983 - refname[0] == '*' &&
984 - (refname[1] == '\0' || refname[1] == '/')) {
985 - /* Accept one wildcard as a full refname component. */
986 - flags &= ~REFNAME_REFSPEC_PATTERN;
987 - component_len = 1;
988 - } else {
989 - return -1;
990 - }
991 - }
992 - component_count++;
993 - if (refname[component_len] == '\0')
994 - break;
995 - /* Skip to next component. */
996 - refname += component_len + 1;
997 - }
998 -
999 - if (refname[component_len - 1] == '.')
1000 - return -1; /* Refname ends with '.'. */
1001 - if (!(flags & REFNAME_ALLOW_ONELEVEL) && component_count < 2)
1002 - return -1; /* Refname has only one component. */
1003 - return 0;
1004 -}
1005 -
1044 const char *prettify_refname(const char *name)
1045 {
1046 return name + (
@@ -1072,35 +1110,6 @@ static int remove_empty_directories(const char *file)
1110 return result;
1111 }
1112
1075 -/*
1076 - * Return true iff a reference named refname could be created without
1077 - * conflicting with the name of an existing reference. If oldrefname
1078 - * is non-NULL, ignore potential conflicts with oldrefname (e.g.,
1079 - * because oldrefname is scheduled for deletion in the same
1080 - * operation).
1081 - */
1082 -static int is_refname_available(const char *refname, const char *oldrefname,
1083 - struct ref_array *array)
1084 -{
1085 - int i, namlen = strlen(refname); /* e.g. 'foo/bar' */
1086 - for (i = 0; i < array->nr; i++ ) {
1087 - struct ref_entry *entry = array->refs[i];
1088 - /* entry->name could be 'foo' or 'foo/bar/baz' */
1089 - if (!oldrefname || strcmp(oldrefname, entry->name)) {
1090 - int len = strlen(entry->name);
1091 - int cmplen = (namlen < len) ? namlen : len;
1092 - const char *lead = (namlen < len) ? entry->name : refname;
1093 - if (!strncmp(refname, entry->name, cmplen) &&
1094 - lead[cmplen] == '/') {
1095 - error("'%s' exists; cannot create '%s'",
1096 - entry->name, refname);
1097 - return 0;
1098 - }
1099 - }
1100 - }
1101 - return 1;
1102 -}
1103 -
1113 /*
1114 * *string and *len will only be substituted, and *string returned (for
1115 * later free()ing) if the string passed in is a magic short-hand form
@@ -2004,12 +2013,6 @@ int update_ref(const char *action, const char *refname,
2013 return 0;
2014 }
2015
2007 -int ref_exists(const char *refname)
2008 -{
2009 - unsigned char sha1[20];
2010 - return !!resolve_ref_unsafe(refname, sha1, 1, NULL);
2011 -}
2012 -
2016 struct ref *find_ref_by_name(const struct ref *list, const char *name)
2017 {
2018 for ( ; list; list = list->next)