refspec: introduce struct refspec

Introduce 'struct refspec', an abstraction around a collection of 'struct refspec_item's much like how 'struct pathspec' holds a collection of 'struct pathspec_item's. A refspec struct also contains an array of the original refspec strings which will be used to facilitate the migration to using this new abstraction throughout the code base. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Brandon Williams committed May 16, 2018 at 15:57 UTC 6d4c05785946e302e611be9ac1f5ca0b5ada9214
2 files changed +89
refspec.c
+64
@@ -178,3 +178,67 @@ void free_refspec(int nr_refspec, struct refspec_item *refspec)
178 }
179 free(refspec);
180 }
181 +
182 +void refspec_item_init(struct refspec_item *item, const char *refspec, int fetch)
183 +{
184 + memset(item, 0, sizeof(*item));
185 +
186 + if (!parse_refspec(item, refspec, fetch))
187 + die("Invalid refspec '%s'", refspec);
188 +}
189 +
190 +void refspec_item_clear(struct refspec_item *item)
191 +{
192 + FREE_AND_NULL(item->src);
193 + FREE_AND_NULL(item->dst);
194 + item->force = 0;
195 + item->pattern = 0;
196 + item->matching = 0;
197 + item->exact_sha1 = 0;
198 +}
199 +
200 +void refspec_init(struct refspec *rs, int fetch)
201 +{
202 + memset(rs, 0, sizeof(*rs));
203 + rs->fetch = fetch;
204 +}
205 +
206 +void refspec_append(struct refspec *rs, const char *refspec)
207 +{
208 + struct refspec_item item;
209 +
210 + refspec_item_init(&item, refspec, rs->fetch);
211 +
212 + ALLOC_GROW(rs->items, rs->nr + 1, rs->alloc);
213 + rs->items[rs->nr++] = item;
214 +
215 + ALLOC_GROW(rs->raw, rs->raw_nr + 1, rs->raw_alloc);
216 + rs->raw[rs->raw_nr++] = xstrdup(refspec);
217 +}
218 +
219 +void refspec_appendn(struct refspec *rs, const char **refspecs, int nr)
220 +{
221 + int i;
222 + for (i = 0; i < nr; i++)
223 + refspec_append(rs, refspecs[i]);
224 +}
225 +
226 +void refspec_clear(struct refspec *rs)
227 +{
228 + int i;
229 +
230 + for (i = 0; i < rs->nr; i++)
231 + refspec_item_clear(&rs->items[i]);
232 +
233 + FREE_AND_NULL(rs->items);
234 + rs->alloc = 0;
235 + rs->nr = 0;
236 +
237 + for (i = 0; i < rs->raw_nr; i++)
238 + free((char *)rs->raw[i]);
239 + FREE_AND_NULL(rs->raw);
240 + rs->raw_alloc = 0;
241 + rs->raw_nr = 0;
242 +
243 + rs->fetch = 0;
244 +}
refspec.h
+25
@@ -20,4 +20,29 @@ struct refspec_item *parse_push_refspec(int nr_refspec, const char **refspec);
20
21 void free_refspec(int nr_refspec, struct refspec_item *refspec);
22
23 +#define REFSPEC_FETCH 1
24 +#define REFSPEC_PUSH 0
25 +
26 +#define REFSPEC_INIT_FETCH { .fetch = REFSPEC_FETCH }
27 +#define REFSPEC_INIT_PUSH { .fetch = REFSPEC_PUSH }
28 +
29 +struct refspec {
30 + struct refspec_item *items;
31 + int alloc;
32 + int nr;
33 +
34 + const char **raw;
35 + int raw_alloc;
36 + int raw_nr;
37 +
38 + int fetch;
39 +};
40 +
41 +void refspec_item_init(struct refspec_item *item, const char *refspec, int fetch);
42 +void refspec_item_clear(struct refspec_item *item);
43 +void refspec_init(struct refspec *rs, int fetch);
44 +void refspec_append(struct refspec *rs, const char *refspec);
45 +void refspec_appendn(struct refspec *rs, const char **refspecs, int nr);
46 +void refspec_clear(struct refspec *rs);
47 +
48 #endif /* REFSPEC_H */