THIS IS A TEST INSTANCE ONLY! REPOSITORIES CAN BE DELETED AT ANY TIME!

Git Source Code Mirror - This is a publish-only repository and all pull requests are ignored. Please follow Documentation/SubmittingPatches procedure for any of your improvements.
git
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
4.9KB

  1. #include "cache.h"
  2. #include "argv-array.h"
  3. #include "refs.h"
  4. #include "refspec.h"
  5. static struct refspec_item s_tag_refspec = {
  6. 0,
  7. 1,
  8. 0,
  9. 0,
  10. "refs/tags/*",
  11. "refs/tags/*"
  12. };
  13. /* See TAG_REFSPEC for the string version */
  14. const struct refspec_item *tag_refspec = &s_tag_refspec;
  15. /*
  16. * Parses the provided refspec 'refspec' and populates the refspec_item 'item'.
  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. is_glob = 0;
  26. lhs = refspec;
  27. if (*lhs == '+') {
  28. item->force = 1;
  29. lhs++;
  30. }
  31. rhs = strrchr(lhs, ':');
  32. /*
  33. * Before going on, special case ":" (or "+:") as a refspec
  34. * for pushing matching refs.
  35. */
  36. if (!fetch && rhs == lhs && rhs[1] == '\0') {
  37. item->matching = 1;
  38. return 1;
  39. }
  40. if (rhs) {
  41. size_t rlen = strlen(++rhs);
  42. is_glob = (1 <= rlen && strchr(rhs, '*'));
  43. item->dst = xstrndup(rhs, rlen);
  44. } else {
  45. item->dst = NULL;
  46. }
  47. llen = (rhs ? (rhs - lhs - 1) : strlen(lhs));
  48. if (1 <= llen && memchr(lhs, '*', llen)) {
  49. if ((rhs && !is_glob) || (!rhs && fetch))
  50. return 0;
  51. is_glob = 1;
  52. } else if (rhs && is_glob) {
  53. return 0;
  54. }
  55. item->pattern = is_glob;
  56. item->src = xstrndup(lhs, llen);
  57. flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
  58. if (fetch) {
  59. struct object_id unused;
  60. /* LHS */
  61. if (!*item->src)
  62. ; /* empty is ok; it means "HEAD" */
  63. else if (llen == the_hash_algo->hexsz && !get_oid_hex(item->src, &unused))
  64. item->exact_sha1 = 1; /* ok */
  65. else if (!check_refname_format(item->src, flags))
  66. ; /* valid looking ref is ok */
  67. else
  68. return 0;
  69. /* RHS */
  70. if (!item->dst)
  71. ; /* missing is ok; it is the same as empty */
  72. else if (!*item->dst)
  73. ; /* empty is ok; it means "do not store" */
  74. else if (!check_refname_format(item->dst, flags))
  75. ; /* valid looking ref is ok */
  76. else
  77. return 0;
  78. } else {
  79. /*
  80. * LHS
  81. * - empty is allowed; it means delete.
  82. * - when wildcarded, it must be a valid looking ref.
  83. * - otherwise, it must be an extended SHA-1, but
  84. * there is no existing way to validate this.
  85. */
  86. if (!*item->src)
  87. ; /* empty is ok */
  88. else if (is_glob) {
  89. if (check_refname_format(item->src, flags))
  90. return 0;
  91. }
  92. else
  93. ; /* anything goes, for now */
  94. /*
  95. * RHS
  96. * - missing is allowed, but LHS then must be a
  97. * valid looking ref.
  98. * - empty is not allowed.
  99. * - otherwise it must be a valid looking ref.
  100. */
  101. if (!item->dst) {
  102. if (check_refname_format(item->src, flags))
  103. return 0;
  104. } else if (!*item->dst) {
  105. return 0;
  106. } else {
  107. if (check_refname_format(item->dst, flags))
  108. return 0;
  109. }
  110. }
  111. return 1;
  112. }
  113. int refspec_item_init(struct refspec_item *item, const char *refspec, int fetch)
  114. {
  115. memset(item, 0, sizeof(*item));
  116. return parse_refspec(item, refspec, fetch);
  117. }
  118. void refspec_item_init_or_die(struct refspec_item *item, const char *refspec,
  119. int fetch)
  120. {
  121. if (!refspec_item_init(item, refspec, fetch))
  122. die(_("invalid refspec '%s'"), refspec);
  123. }
  124. void refspec_item_clear(struct refspec_item *item)
  125. {
  126. FREE_AND_NULL(item->src);
  127. FREE_AND_NULL(item->dst);
  128. item->force = 0;
  129. item->pattern = 0;
  130. item->matching = 0;
  131. item->exact_sha1 = 0;
  132. }
  133. void refspec_init(struct refspec *rs, int fetch)
  134. {
  135. memset(rs, 0, sizeof(*rs));
  136. rs->fetch = fetch;
  137. }
  138. void refspec_append(struct refspec *rs, const char *refspec)
  139. {
  140. struct refspec_item item;
  141. refspec_item_init_or_die(&item, refspec, rs->fetch);
  142. ALLOC_GROW(rs->items, rs->nr + 1, rs->alloc);
  143. rs->items[rs->nr++] = item;
  144. ALLOC_GROW(rs->raw, rs->raw_nr + 1, rs->raw_alloc);
  145. rs->raw[rs->raw_nr++] = xstrdup(refspec);
  146. }
  147. void refspec_appendn(struct refspec *rs, const char **refspecs, int nr)
  148. {
  149. int i;
  150. for (i = 0; i < nr; i++)
  151. refspec_append(rs, refspecs[i]);
  152. }
  153. void refspec_clear(struct refspec *rs)
  154. {
  155. int i;
  156. for (i = 0; i < rs->nr; i++)
  157. refspec_item_clear(&rs->items[i]);
  158. FREE_AND_NULL(rs->items);
  159. rs->alloc = 0;
  160. rs->nr = 0;
  161. for (i = 0; i < rs->raw_nr; i++)
  162. free((char *)rs->raw[i]);
  163. FREE_AND_NULL(rs->raw);
  164. rs->raw_alloc = 0;
  165. rs->raw_nr = 0;
  166. rs->fetch = 0;
  167. }
  168. int valid_fetch_refspec(const char *fetch_refspec_str)
  169. {
  170. struct refspec_item refspec;
  171. int ret = refspec_item_init(&refspec, fetch_refspec_str, REFSPEC_FETCH);
  172. refspec_item_clear(&refspec);
  173. return ret;
  174. }
  175. void refspec_ref_prefixes(const struct refspec *rs,
  176. struct argv_array *ref_prefixes)
  177. {
  178. int i;
  179. for (i = 0; i < rs->nr; i++) {
  180. const struct refspec_item *item = &rs->items[i];
  181. const char *prefix = NULL;
  182. if (item->exact_sha1)
  183. continue;
  184. if (rs->fetch == REFSPEC_FETCH)
  185. prefix = item->src;
  186. else if (item->dst)
  187. prefix = item->dst;
  188. else if (item->src && !item->exact_sha1)
  189. prefix = item->src;
  190. if (prefix) {
  191. if (item->pattern) {
  192. const char *glob = strchr(prefix, '*');
  193. argv_array_pushf(ref_prefixes, "%.*s",
  194. (int)(glob - prefix),
  195. prefix);
  196. } else {
  197. expand_ref_prefix(ref_prefixes, prefix);
  198. }
  199. }
  200. }
  201. }