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)