* Parses the provided refspec 'refspec' and populates the refspec_item 'item'. * Returns 1 if successful and 0 if the refspec is invalid. */
| 17 | * Returns 1 if successful and 0 if the refspec is invalid. |
| 18 | */ |
| 19 | static int parse_refspec(struct refspec_item *item, const char *refspec, int fetch) |
| 20 | { |
| 21 | size_t llen; |
| 22 | int is_glob; |
| 23 | const char *lhs, *rhs; |
| 24 | int flags; |
| 25 | |
| 26 | is_glob = 0; |
| 27 | |
| 28 | lhs = refspec; |
| 29 | if (*lhs == '+') { |
| 30 | item->force = 1; |
| 31 | lhs++; |
| 32 | } else if (*lhs == '^') { |
| 33 | item->negative = 1; |
| 34 | lhs++; |
| 35 | } |
| 36 | |
| 37 | rhs = strrchr(lhs, ':'); |
| 38 | |
| 39 | /* negative refspecs only have one side */ |
| 40 | if (item->negative && rhs) |
| 41 | return 0; |
| 42 | |
| 43 | /* |
| 44 | * Before going on, special case ":" (or "+:") as a refspec |
| 45 | * for pushing matching refs. |
| 46 | */ |
| 47 | if (!fetch && rhs == lhs && rhs[1] == '\0') { |
| 48 | item->matching = 1; |
| 49 | return 1; |
| 50 | } |
| 51 | |
| 52 | if (rhs) { |
| 53 | size_t rlen = strlen(++rhs); |
| 54 | is_glob = (1 <= rlen && strchr(rhs, '*')); |
| 55 | item->dst = xstrndup(rhs, rlen); |
| 56 | } else { |
| 57 | item->dst = NULL; |
| 58 | } |
| 59 | |
| 60 | llen = (rhs ? (rhs - lhs - 1) : strlen(lhs)); |
| 61 | if (1 <= llen && memchr(lhs, '*', llen)) { |
| 62 | if ((rhs && !is_glob) || (!rhs && !item->negative && fetch)) |
| 63 | return 0; |
| 64 | is_glob = 1; |
| 65 | } else if (rhs && is_glob) { |
| 66 | return 0; |
| 67 | } |
| 68 | |
| 69 | item->pattern = is_glob; |
| 70 | if (llen == 1 && *lhs == '@') |
| 71 | item->src = xstrdup("HEAD"); |
| 72 | else |
| 73 | item->src = xstrndup(lhs, llen); |
| 74 | flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0); |
| 75 | |
| 76 | if (item->negative) { |
no test coverage detected