summaryrefslogtreecommitdiff
path: root/refspec.c
diff options
context:
space:
mode:
authorBrandon Williams <bmwill@google.com>2018-05-16 22:57:50 (GMT)
committerJunio C Hamano <gitster@pobox.com>2018-05-17 21:19:42 (GMT)
commit3eec3700fdc4d5b0a33729d45e7fb9735ed7e0f5 (patch)
tree9265ca72fb70f6838dbac26e9d097aed52ad63f6 /refspec.c
parent0ad4a5ff50dbc839ae26aa60c03b55bf416b6000 (diff)
downloadgit-3eec3700fdc4d5b0a33729d45e7fb9735ed7e0f5.zip
git-3eec3700fdc4d5b0a33729d45e7fb9735ed7e0f5.tar.gz
git-3eec3700fdc4d5b0a33729d45e7fb9735ed7e0f5.tar.bz2
refspec: factor out parsing a single refspec
Factor out the logic which parses a single refspec into its own function. This makes it easier to reuse this logic in a future patch. Signed-off-by: Brandon Williams <bmwill@google.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'refspec.c')
-rw-r--r--refspec.c195
1 files changed, 104 insertions, 91 deletions
diff --git a/refspec.c b/refspec.c
index 22188f0..8bf4ebb 100644
--- a/refspec.c
+++ b/refspec.c
@@ -14,110 +14,123 @@ static struct refspec_item s_tag_refspec = {
/* See TAG_REFSPEC for the string version */
const struct refspec_item *tag_refspec = &s_tag_refspec;
-static struct refspec_item *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
+/*
+ * Parses the provided refspec 'refspec' and populates the refspec_item 'item'.
+ * Returns 1 if successful and 0 if the refspec is invalid.
+ */
+static int parse_refspec(struct refspec_item *item, const char *refspec, int fetch)
{
- int i;
- struct refspec_item *rs = xcalloc(nr_refspec, sizeof(*rs));
+ size_t llen;
+ int is_glob;
+ const char *lhs, *rhs;
+ int flags;
- for (i = 0; i < nr_refspec; i++) {
- size_t llen;
- int is_glob;
- const char *lhs, *rhs;
- int flags;
+ is_glob = 0;
- is_glob = 0;
+ lhs = refspec;
+ if (*lhs == '+') {
+ item->force = 1;
+ lhs++;
+ }
- lhs = refspec[i];
- if (*lhs == '+') {
- rs[i].force = 1;
- lhs++;
- }
+ rhs = strrchr(lhs, ':');
- rhs = strrchr(lhs, ':');
+ /*
+ * Before going on, special case ":" (or "+:") as a refspec
+ * for pushing matching refs.
+ */
+ if (!fetch && rhs == lhs && rhs[1] == '\0') {
+ item->matching = 1;
+ return 1;
+ }
+ if (rhs) {
+ size_t rlen = strlen(++rhs);
+ is_glob = (1 <= rlen && strchr(rhs, '*'));
+ item->dst = xstrndup(rhs, rlen);
+ }
+
+ llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
+ if (1 <= llen && memchr(lhs, '*', llen)) {
+ if ((rhs && !is_glob) || (!rhs && fetch))
+ return 0;
+ is_glob = 1;
+ } else if (rhs && is_glob) {
+ return 0;
+ }
+
+ item->pattern = is_glob;
+ item->src = xstrndup(lhs, llen);
+ flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
+
+ if (fetch) {
+ struct object_id unused;
+
+ /* LHS */
+ if (!*item->src)
+ ; /* empty is ok; it means "HEAD" */
+ else if (llen == GIT_SHA1_HEXSZ && !get_oid_hex(item->src, &unused))
+ item->exact_sha1 = 1; /* ok */
+ else if (!check_refname_format(item->src, flags))
+ ; /* valid looking ref is ok */
+ else
+ return 0;
+ /* RHS */
+ if (!item->dst)
+ ; /* missing is ok; it is the same as empty */
+ else if (!*item->dst)
+ ; /* empty is ok; it means "do not store" */
+ else if (!check_refname_format(item->dst, flags))
+ ; /* valid looking ref is ok */
+ else
+ return 0;
+ } else {
/*
- * Before going on, special case ":" (or "+:") as a refspec
- * for pushing matching refs.
+ * LHS
+ * - empty is allowed; it means delete.
+ * - when wildcarded, it must be a valid looking ref.
+ * - otherwise, it must be an extended SHA-1, but
+ * there is no existing way to validate this.
*/
- if (!fetch && rhs == lhs && rhs[1] == '\0') {
- rs[i].matching = 1;
- continue;
+ if (!*item->src)
+ ; /* empty is ok */
+ else if (is_glob) {
+ if (check_refname_format(item->src, flags))
+ return 0;
}
-
- if (rhs) {
- size_t rlen = strlen(++rhs);
- is_glob = (1 <= rlen && strchr(rhs, '*'));
- rs[i].dst = xstrndup(rhs, rlen);
+ else
+ ; /* anything goes, for now */
+ /*
+ * RHS
+ * - missing is allowed, but LHS then must be a
+ * valid looking ref.
+ * - empty is not allowed.
+ * - otherwise it must be a valid looking ref.
+ */
+ if (!item->dst) {
+ if (check_refname_format(item->src, flags))
+ return 0;
+ } else if (!*item->dst) {
+ return 0;
+ } else {
+ if (check_refname_format(item->dst, flags))
+ return 0;
}
+ }
- llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
- if (1 <= llen && memchr(lhs, '*', llen)) {
- if ((rhs && !is_glob) || (!rhs && fetch))
- goto invalid;
- is_glob = 1;
- } else if (rhs && is_glob) {
- goto invalid;
- }
+ return 1;
+}
- rs[i].pattern = is_glob;
- rs[i].src = xstrndup(lhs, llen);
- flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
-
- if (fetch) {
- struct object_id unused;
-
- /* LHS */
- if (!*rs[i].src)
- ; /* empty is ok; it means "HEAD" */
- else if (llen == GIT_SHA1_HEXSZ && !get_oid_hex(rs[i].src, &unused))
- rs[i].exact_sha1 = 1; /* ok */
- else if (!check_refname_format(rs[i].src, flags))
- ; /* valid looking ref is ok */
- else
- goto invalid;
- /* RHS */
- if (!rs[i].dst)
- ; /* missing is ok; it is the same as empty */
- else if (!*rs[i].dst)
- ; /* empty is ok; it means "do not store" */
- else if (!check_refname_format(rs[i].dst, flags))
- ; /* valid looking ref is ok */
- else
- goto invalid;
- } else {
- /*
- * LHS
- * - empty is allowed; it means delete.
- * - when wildcarded, it must be a valid looking ref.
- * - otherwise, it must be an extended SHA-1, but
- * there is no existing way to validate this.
- */
- if (!*rs[i].src)
- ; /* empty is ok */
- else if (is_glob) {
- if (check_refname_format(rs[i].src, flags))
- goto invalid;
- }
- else
- ; /* anything goes, for now */
- /*
- * RHS
- * - missing is allowed, but LHS then must be a
- * valid looking ref.
- * - empty is not allowed.
- * - otherwise it must be a valid looking ref.
- */
- if (!rs[i].dst) {
- if (check_refname_format(rs[i].src, flags))
- goto invalid;
- } else if (!*rs[i].dst) {
- goto invalid;
- } else {
- if (check_refname_format(rs[i].dst, flags))
- goto invalid;
- }
- }
+static struct refspec_item *parse_refspec_internal(int nr_refspec, const char **refspec, int fetch, int verify)
+{
+ 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;
}
+
return rs;
invalid: