#include "cache.h"
+#include "argv-array.h"
#include "refs.h"
#include "refspec.h"
size_t rlen = strlen(++rhs);
is_glob = (1 <= rlen && strchr(rhs, '*'));
item->dst = xstrndup(rhs, rlen);
+ } else {
+ item->dst = NULL;
}
llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
return 1;
}
-static struct refspec_item *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
+void refspec_item_init(struct refspec_item *item, const char *refspec, int fetch)
{
- int i;
- struct refspec_item *rs = xcalloc(nr_refspec, sizeof(*rs));
-
- for (i = 0; i < nr_refspec; i++) {
- if (!parse_refspec(&rs[i], refspec[i], fetch))
- goto invalid;
- }
+ memset(item, 0, sizeof(*item));
- return rs;
-
- invalid:
- if (verify) {
- /*
- * nr_refspec must be greater than zero and i must be valid
- * since it is only possible to reach this point from within
- * the for loop above.
- */
- free_refspec(i+1, rs);
- return NULL;
- }
- die("Invalid refspec '%s'", refspec[i]);
+ if (!parse_refspec(item, refspec, fetch))
+ die("Invalid refspec '%s'", refspec);
}
-int valid_fetch_refspec(const char *fetch_refspec_str)
+void refspec_item_clear(struct refspec_item *item)
{
- struct refspec_item *refspec;
+ FREE_AND_NULL(item->src);
+ FREE_AND_NULL(item->dst);
+ item->force = 0;
+ item->pattern = 0;
+ item->matching = 0;
+ item->exact_sha1 = 0;
+}
- refspec = parse_refspec_internal(1, &fetch_refspec_str, 1, 1);
- free_refspec(1, refspec);
- return !!refspec;
+void refspec_init(struct refspec *rs, int fetch)
+{
+ memset(rs, 0, sizeof(*rs));
+ rs->fetch = fetch;
}
-struct refspec_item *parse_fetch_refspec(int nr_refspec, const char **refspec)
+void refspec_append(struct refspec *rs, const char *refspec)
{
- return parse_refspec_internal(nr_refspec, refspec, 1, 0);
+ struct refspec_item item;
+
+ refspec_item_init(&item, refspec, rs->fetch);
+
+ ALLOC_GROW(rs->items, rs->nr + 1, rs->alloc);
+ rs->items[rs->nr++] = item;
+
+ ALLOC_GROW(rs->raw, rs->raw_nr + 1, rs->raw_alloc);
+ rs->raw[rs->raw_nr++] = xstrdup(refspec);
}
-struct refspec_item *parse_push_refspec(int nr_refspec, const char **refspec)
+void refspec_appendn(struct refspec *rs, const char **refspecs, int nr)
{
- return parse_refspec_internal(nr_refspec, refspec, 0, 0);
+ int i;
+ for (i = 0; i < nr; i++)
+ refspec_append(rs, refspecs[i]);
}
-void free_refspec(int nr_refspec, struct refspec_item *refspec)
+void refspec_clear(struct refspec *rs)
{
int i;
- if (!refspec)
- return;
+ for (i = 0; i < rs->nr; i++)
+ refspec_item_clear(&rs->items[i]);
+
+ FREE_AND_NULL(rs->items);
+ rs->alloc = 0;
+ rs->nr = 0;
+
+ for (i = 0; i < rs->raw_nr; i++)
+ free((char *)rs->raw[i]);
+ FREE_AND_NULL(rs->raw);
+ rs->raw_alloc = 0;
+ rs->raw_nr = 0;
- for (i = 0; i < nr_refspec; i++) {
- free(refspec[i].src);
- free(refspec[i].dst);
+ rs->fetch = 0;
+}
+
+int valid_fetch_refspec(const char *fetch_refspec_str)
+{
+ struct refspec_item refspec;
+ int ret = parse_refspec(&refspec, fetch_refspec_str, REFSPEC_FETCH);
+ refspec_item_clear(&refspec);
+ return ret;
+}
+
+void refspec_ref_prefixes(const struct refspec *rs,
+ struct argv_array *ref_prefixes)
+{
+ int i;
+ for (i = 0; i < rs->nr; i++) {
+ const struct refspec_item *item = &rs->items[i];
+ const char *prefix = NULL;
+
+ if (item->exact_sha1)
+ continue;
+ if (rs->fetch == REFSPEC_FETCH)
+ prefix = item->src;
+ else if (item->dst)
+ prefix = item->dst;
+ else if (item->src && !item->exact_sha1)
+ prefix = item->src;
+
+ if (prefix) {
+ if (item->pattern) {
+ const char *glob = strchr(prefix, '*');
+ argv_array_pushf(ref_prefixes, "%.*s",
+ (int)(glob - prefix),
+ prefix);
+ } else {
+ expand_ref_prefix(ref_prefixes, prefix);
+ }
+ }
}
- free(refspec);
}