@@ -11,9 +11,13 @@ typedef struct config_entry_list {
1111 struct config_entry_list * next ;
1212 struct config_entry_list * last ;
1313 git_config_entry * entry ;
14- bool first ;
1514} config_entry_list ;
1615
16+ typedef struct {
17+ git_config_entry * entry ;
18+ bool multivar ;
19+ } config_entry_map_head ;
20+
1721typedef struct config_entries_iterator {
1822 git_config_iterator parent ;
1923 git_config_entries * entries ;
@@ -102,14 +106,16 @@ void git_config_entries_incref(git_config_entries *entries)
102106static void config_entries_free (git_config_entries * entries )
103107{
104108 config_entry_list * list = NULL , * next ;
109+ config_entry_map_head * head ;
105110
111+ git_strmap_foreach_value (entries -> map , head ,
112+ git__free ((char * ) head -> entry -> name ); git__free (head )
113+ );
106114 git_strmap_free (entries -> map );
107115
108116 list = entries -> list ;
109117 while (list != NULL ) {
110118 next = list -> next ;
111- if (list -> first )
112- git__free ((char * ) list -> entry -> name );
113119 git__free ((char * ) list -> entry -> value );
114120 git__free (list -> entry );
115121 git__free (list );
@@ -127,40 +133,42 @@ void git_config_entries_free(git_config_entries *entries)
127133
128134int git_config_entries_append (git_config_entries * entries , git_config_entry * entry )
129135{
130- config_entry_list * existing , * head ;
131-
132- head = git__calloc (1 , sizeof (config_entry_list ));
133- GIT_ERROR_CHECK_ALLOC (head );
134- head -> entry = entry ;
135-
136- /*
137- * This is a micro-optimization for configuration files
138- * with a lot of same keys. As for multivars the entry's
139- * key will be the same for all entries, we can just free
140- * all except the first entry's name and just re-use it.
141- */
142- if ((existing = git_strmap_get (entries -> map , entry -> name )) != NULL ) {
136+ config_entry_list * list_head ;
137+ config_entry_map_head * map_head ;
138+
139+ if ((map_head = git_strmap_get (entries -> map , entry -> name )) != NULL ) {
140+ map_head -> multivar = true;
141+ /*
142+ * This is a micro-optimization for configuration files
143+ * with a lot of same keys. As for multivars the entry's
144+ * key will be the same for all entries, we can just free
145+ * all except the first entry's name and just re-use it.
146+ */
143147 git__free ((char * ) entry -> name );
144- entry -> name = existing -> entry -> name ;
148+ entry -> name = map_head -> entry -> name ;
145149 } else {
146- head -> first = 1 ;
150+ map_head = git__calloc (1 , sizeof (* map_head ));
151+ if ((git_strmap_set (entries -> map , entry -> name , map_head )) < 0 )
152+ return -1 ;
147153 }
154+ map_head -> entry = entry ;
155+
156+ list_head = git__calloc (1 , sizeof (config_entry_list ));
157+ GIT_ERROR_CHECK_ALLOC (list_head );
158+ list_head -> entry = entry ;
148159
149160 if (entries -> list )
150- entries -> list -> last -> next = head ;
161+ entries -> list -> last -> next = list_head ;
151162 else
152- entries -> list = head ;
153- entries -> list -> last = head ;
154-
155- if (git_strmap_set (entries -> map , entry -> name , head ) < 0 )
156- return -1 ;
163+ entries -> list = list_head ;
164+ entries -> list -> last = list_head ;
157165
158166 return 0 ;
159167}
160168
161169int git_config_entries_get (git_config_entry * * out , git_config_entries * entries , const char * key )
162170{
163- config_entry_list * entry ;
171+ config_entry_map_head * entry ;
164172 if ((entry = git_strmap_get (entries -> map , key )) == NULL )
165173 return GIT_ENOTFOUND ;
166174 * out = entry -> entry ;
@@ -169,12 +177,12 @@ int git_config_entries_get(git_config_entry **out, git_config_entries *entries,
169177
170178int git_config_entries_get_unique (git_config_entry * * out , git_config_entries * entries , const char * key )
171179{
172- config_entry_list * entry ;
180+ config_entry_map_head * entry ;
173181
174182 if ((entry = git_strmap_get (entries -> map , key )) == NULL )
175183 return GIT_ENOTFOUND ;
176184
177- if (! entry -> first ) {
185+ if (entry -> multivar ) {
178186 git_error_set (GIT_ERROR_CONFIG , "entry is not unique due to being a multivar" );
179187 return -1 ;
180188 }
0 commit comments