@@ -34,7 +34,6 @@ struct git_attr {
34
34
int maybe_real ;
35
35
char name [FLEX_ARRAY ]; /* attribute name */
36
36
};
37
- static int attr_nr ;
38
37
39
38
/*
40
39
* NEEDSWORK: maybe-real, maybe-macro are not property of
@@ -45,9 +44,6 @@ static int attr_nr;
45
44
*/
46
45
static int cannot_trust_maybe_real ;
47
46
48
- /* NEEDSWORK: This will become per git_attr_check */
49
- static struct attr_check_item * check_all_attr ;
50
-
51
47
const char * git_attr_name (const struct git_attr * attr )
52
48
{
53
49
return attr -> name ;
@@ -143,6 +139,57 @@ static void attr_hashmap_add(struct attr_hashmap *map,
143
139
hashmap_add (& map -> map , e );
144
140
}
145
141
142
+ struct all_attrs_item {
143
+ const struct git_attr * attr ;
144
+ const char * value ;
145
+ };
146
+
147
+ /*
148
+ * Reallocate and reinitialize the array of all attributes (which is used in
149
+ * the attribute collection process) in 'check' based on the global dictionary
150
+ * of attributes.
151
+ */
152
+ static void all_attrs_init (struct attr_hashmap * map , struct attr_check * check )
153
+ {
154
+ int i ;
155
+
156
+ hashmap_lock (map );
157
+
158
+ if (map -> map .size < check -> all_attrs_nr )
159
+ die ("BUG: interned attributes shouldn't be deleted" );
160
+
161
+ /*
162
+ * If the number of attributes in the global dictionary has increased
163
+ * (or this attr_check instance doesn't have an initialized all_attrs
164
+ * field), reallocate the provided attr_check instance's all_attrs
165
+ * field and fill each entry with its corresponding git_attr.
166
+ */
167
+ if (map -> map .size != check -> all_attrs_nr ) {
168
+ struct attr_hash_entry * e ;
169
+ struct hashmap_iter iter ;
170
+ hashmap_iter_init (& map -> map , & iter );
171
+
172
+ REALLOC_ARRAY (check -> all_attrs , map -> map .size );
173
+ check -> all_attrs_nr = map -> map .size ;
174
+
175
+ while ((e = hashmap_iter_next (& iter ))) {
176
+ const struct git_attr * a = e -> value ;
177
+ check -> all_attrs [a -> attr_nr ].attr = a ;
178
+ }
179
+ }
180
+
181
+ hashmap_unlock (map );
182
+
183
+ /*
184
+ * Re-initialize every entry in check->all_attrs.
185
+ * This re-initialization can live outside of the locked region since
186
+ * the attribute dictionary is no longer being accessed.
187
+ */
188
+ for (i = 0 ; i < check -> all_attrs_nr ; i ++ ) {
189
+ check -> all_attrs [i ].value = ATTR__UNKNOWN ;
190
+ }
191
+ }
192
+
146
193
static int attr_name_valid (const char * name , size_t namelen )
147
194
{
148
195
/*
@@ -196,16 +243,6 @@ static struct git_attr *git_attr_internal(const char *name, int namelen)
196
243
197
244
attr_hashmap_add (& g_attr_hashmap , a -> name , namelen , a );
198
245
assert (a -> attr_nr == (g_attr_hashmap .map .size - 1 ));
199
-
200
- /*
201
- * NEEDSWORK: per git_attr_check check_all_attr
202
- * will be initialized a lot more lazily, not
203
- * like this, and not here.
204
- */
205
- REALLOC_ARRAY (check_all_attr , ++ attr_nr );
206
- check_all_attr [a -> attr_nr ].attr = a ;
207
- check_all_attr [a -> attr_nr ].value = ATTR__UNKNOWN ;
208
- assert (a -> attr_nr == (attr_nr - 1 ));
209
246
}
210
247
211
248
hashmap_unlock (& g_attr_hashmap );
@@ -513,6 +550,10 @@ void attr_check_clear(struct attr_check *check)
513
550
check -> items = NULL ;
514
551
check -> alloc = 0 ;
515
552
check -> nr = 0 ;
553
+
554
+ free (check -> all_attrs );
555
+ check -> all_attrs = NULL ;
556
+ check -> all_attrs_nr = 0 ;
516
557
}
517
558
518
559
void attr_check_free (struct attr_check * check )
@@ -860,16 +901,16 @@ static int path_matches(const char *pathname, int pathlen,
860
901
pattern , prefix , pat -> patternlen , pat -> flags );
861
902
}
862
903
863
- static int macroexpand_one (int attr_nr , int rem );
904
+ static int macroexpand_one (struct all_attrs_item * all_attrs , int nr , int rem );
864
905
865
- static int fill_one (const char * what , struct match_attr * a , int rem )
906
+ static int fill_one (const char * what , struct all_attrs_item * all_attrs ,
907
+ struct match_attr * a , int rem )
866
908
{
867
- struct attr_check_item * check = check_all_attr ;
868
909
int i ;
869
910
870
- for (i = a -> num_attr - 1 ; 0 < rem && 0 <= i ; i -- ) {
911
+ for (i = a -> num_attr - 1 ; rem > 0 && i >= 0 ; i -- ) {
871
912
struct git_attr * attr = a -> state [i ].attr ;
872
- const char * * n = & (check [attr -> attr_nr ].value );
913
+ const char * * n = & (all_attrs [attr -> attr_nr ].value );
873
914
const char * v = a -> state [i ].setto ;
874
915
875
916
if (* n == ATTR__UNKNOWN ) {
@@ -878,14 +919,15 @@ static int fill_one(const char *what, struct match_attr *a, int rem)
878
919
attr , v );
879
920
* n = v ;
880
921
rem -- ;
881
- rem = macroexpand_one (attr -> attr_nr , rem );
922
+ rem = macroexpand_one (all_attrs , attr -> attr_nr , rem );
882
923
}
883
924
}
884
925
return rem ;
885
926
}
886
927
887
928
static int fill (const char * path , int pathlen , int basename_offset ,
888
- struct attr_stack * stk , int rem )
929
+ struct attr_stack * stk , struct all_attrs_item * all_attrs ,
930
+ int rem )
889
931
{
890
932
int i ;
891
933
const char * base = stk -> origin ? stk -> origin : "" ;
@@ -896,18 +938,18 @@ static int fill(const char *path, int pathlen, int basename_offset,
896
938
continue ;
897
939
if (path_matches (path , pathlen , basename_offset ,
898
940
& a -> u .pat , base , stk -> originlen ))
899
- rem = fill_one ("fill" , a , rem );
941
+ rem = fill_one ("fill" , all_attrs , a , rem );
900
942
}
901
943
return rem ;
902
944
}
903
945
904
- static int macroexpand_one (int nr , int rem )
946
+ static int macroexpand_one (struct all_attrs_item * all_attrs , int nr , int rem )
905
947
{
906
948
struct attr_stack * stk ;
907
949
int i ;
908
950
909
- if (check_all_attr [nr ].value != ATTR__TRUE ||
910
- !check_all_attr [nr ].attr -> maybe_macro )
951
+ if (all_attrs [nr ].value != ATTR__TRUE ||
952
+ !all_attrs [nr ].attr -> maybe_macro )
911
953
return rem ;
912
954
913
955
for (stk = attr_stack ; stk ; stk = stk -> prev ) {
@@ -916,17 +958,17 @@ static int macroexpand_one(int nr, int rem)
916
958
if (!ma -> is_macro )
917
959
continue ;
918
960
if (ma -> u .attr -> attr_nr == nr )
919
- return fill_one ("expand" , ma , rem );
961
+ return fill_one ("expand" , all_attrs , ma , rem );
920
962
}
921
963
}
922
964
923
965
return rem ;
924
966
}
925
967
926
968
/*
927
- * Collect attributes for path into the array pointed to by
928
- * check_all_attr. If num is non-zero, only attributes in check[] are
929
- * collected. Otherwise all attributes are collected.
969
+ * Collect attributes for path into the array pointed to by check->all_attrs.
970
+ * If check->check_nr is non-zero, only attributes in check[] are collected.
971
+ * Otherwise all attributes are collected.
930
972
*/
931
973
static void collect_some_attrs (const char * path , struct attr_check * check )
932
974
{
@@ -949,15 +991,15 @@ static void collect_some_attrs(const char *path, struct attr_check *check)
949
991
}
950
992
951
993
prepare_attr_stack (path , dirlen );
952
- for ( i = 0 ; i < attr_nr ; i ++ )
953
- check_all_attr [ i ]. value = ATTR__UNKNOWN ;
994
+ all_attrs_init ( & g_attr_hashmap , check );
995
+
954
996
if (check -> nr && !cannot_trust_maybe_real ) {
955
997
rem = 0 ;
956
998
for (i = 0 ; i < check -> nr ; i ++ ) {
957
999
const struct git_attr * a = check -> items [i ].attr ;
958
1000
if (!a -> maybe_real ) {
959
- struct attr_check_item * c ;
960
- c = check_all_attr + a -> attr_nr ;
1001
+ struct all_attrs_item * c ;
1002
+ c = check -> all_attrs + a -> attr_nr ;
961
1003
c -> value = ATTR__UNSET ;
962
1004
rem ++ ;
963
1005
}
@@ -966,9 +1008,9 @@ static void collect_some_attrs(const char *path, struct attr_check *check)
966
1008
return ;
967
1009
}
968
1010
969
- rem = attr_nr ;
1011
+ rem = check -> all_attrs_nr ;
970
1012
for (stk = attr_stack ; 0 < rem && stk ; stk = stk -> prev )
971
- rem = fill (path , pathlen , basename_offset , stk , rem );
1013
+ rem = fill (path , pathlen , basename_offset , stk , check -> all_attrs , rem );
972
1014
}
973
1015
974
1016
int git_check_attr (const char * path , struct attr_check * check )
@@ -978,7 +1020,8 @@ int git_check_attr(const char *path, struct attr_check *check)
978
1020
collect_some_attrs (path , check );
979
1021
980
1022
for (i = 0 ; i < check -> nr ; i ++ ) {
981
- const char * value = check_all_attr [check -> items [i ].attr -> attr_nr ].value ;
1023
+ size_t n = check -> items [i ].attr -> attr_nr ;
1024
+ const char * value = check -> all_attrs [n ].value ;
982
1025
if (value == ATTR__UNKNOWN )
983
1026
value = ATTR__UNSET ;
984
1027
check -> items [i ].value = value ;
@@ -994,9 +1037,9 @@ void git_all_attrs(const char *path, struct attr_check *check)
994
1037
attr_check_reset (check );
995
1038
collect_some_attrs (path , check );
996
1039
997
- for (i = 0 ; i < attr_nr ; i ++ ) {
998
- const char * name = check_all_attr [i ].attr -> name ;
999
- const char * value = check_all_attr [i ].value ;
1040
+ for (i = 0 ; i < check -> all_attrs_nr ; i ++ ) {
1041
+ const char * name = check -> all_attrs [i ].attr -> name ;
1042
+ const char * value = check -> all_attrs [i ].value ;
1000
1043
struct attr_check_item * item ;
1001
1044
if (value == ATTR__UNSET || value == ATTR__UNKNOWN )
1002
1045
continue ;
0 commit comments