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.

436 lines
10KB

  1. /*
  2. * Generic reference iterator infrastructure. See refs-internal.h for
  3. * documentation about the design and use of reference iterators.
  4. */
  5. #include "cache.h"
  6. #include "refs.h"
  7. #include "refs/refs-internal.h"
  8. #include "iterator.h"
  9. int ref_iterator_advance(struct ref_iterator *ref_iterator)
  10. {
  11. return ref_iterator->vtable->advance(ref_iterator);
  12. }
  13. int ref_iterator_peel(struct ref_iterator *ref_iterator,
  14. struct object_id *peeled)
  15. {
  16. return ref_iterator->vtable->peel(ref_iterator, peeled);
  17. }
  18. int ref_iterator_abort(struct ref_iterator *ref_iterator)
  19. {
  20. return ref_iterator->vtable->abort(ref_iterator);
  21. }
  22. void base_ref_iterator_init(struct ref_iterator *iter,
  23. struct ref_iterator_vtable *vtable,
  24. int ordered)
  25. {
  26. iter->vtable = vtable;
  27. iter->ordered = !!ordered;
  28. iter->refname = NULL;
  29. iter->oid = NULL;
  30. iter->flags = 0;
  31. }
  32. void base_ref_iterator_free(struct ref_iterator *iter)
  33. {
  34. /* Help make use-after-free bugs fail quickly: */
  35. iter->vtable = NULL;
  36. free(iter);
  37. }
  38. struct empty_ref_iterator {
  39. struct ref_iterator base;
  40. };
  41. static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator)
  42. {
  43. return ref_iterator_abort(ref_iterator);
  44. }
  45. static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator,
  46. struct object_id *peeled)
  47. {
  48. BUG("peel called for empty iterator");
  49. }
  50. static int empty_ref_iterator_abort(struct ref_iterator *ref_iterator)
  51. {
  52. base_ref_iterator_free(ref_iterator);
  53. return ITER_DONE;
  54. }
  55. static struct ref_iterator_vtable empty_ref_iterator_vtable = {
  56. empty_ref_iterator_advance,
  57. empty_ref_iterator_peel,
  58. empty_ref_iterator_abort
  59. };
  60. struct ref_iterator *empty_ref_iterator_begin(void)
  61. {
  62. struct empty_ref_iterator *iter = xcalloc(1, sizeof(*iter));
  63. struct ref_iterator *ref_iterator = &iter->base;
  64. base_ref_iterator_init(ref_iterator, &empty_ref_iterator_vtable, 1);
  65. return ref_iterator;
  66. }
  67. int is_empty_ref_iterator(struct ref_iterator *ref_iterator)
  68. {
  69. return ref_iterator->vtable == &empty_ref_iterator_vtable;
  70. }
  71. struct merge_ref_iterator {
  72. struct ref_iterator base;
  73. struct ref_iterator *iter0, *iter1;
  74. ref_iterator_select_fn *select;
  75. void *cb_data;
  76. /*
  77. * A pointer to iter0 or iter1 (whichever is supplying the
  78. * current value), or NULL if advance has not yet been called.
  79. */
  80. struct ref_iterator **current;
  81. };
  82. static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
  83. {
  84. struct merge_ref_iterator *iter =
  85. (struct merge_ref_iterator *)ref_iterator;
  86. int ok;
  87. if (!iter->current) {
  88. /* Initialize: advance both iterators to their first entries */
  89. if ((ok = ref_iterator_advance(iter->iter0)) != ITER_OK) {
  90. iter->iter0 = NULL;
  91. if (ok == ITER_ERROR)
  92. goto error;
  93. }
  94. if ((ok = ref_iterator_advance(iter->iter1)) != ITER_OK) {
  95. iter->iter1 = NULL;
  96. if (ok == ITER_ERROR)
  97. goto error;
  98. }
  99. } else {
  100. /*
  101. * Advance the current iterator past the just-used
  102. * entry:
  103. */
  104. if ((ok = ref_iterator_advance(*iter->current)) != ITER_OK) {
  105. *iter->current = NULL;
  106. if (ok == ITER_ERROR)
  107. goto error;
  108. }
  109. }
  110. /* Loop until we find an entry that we can yield. */
  111. while (1) {
  112. struct ref_iterator **secondary;
  113. enum iterator_selection selection =
  114. iter->select(iter->iter0, iter->iter1, iter->cb_data);
  115. if (selection == ITER_SELECT_DONE) {
  116. return ref_iterator_abort(ref_iterator);
  117. } else if (selection == ITER_SELECT_ERROR) {
  118. ref_iterator_abort(ref_iterator);
  119. return ITER_ERROR;
  120. }
  121. if ((selection & ITER_CURRENT_SELECTION_MASK) == 0) {
  122. iter->current = &iter->iter0;
  123. secondary = &iter->iter1;
  124. } else {
  125. iter->current = &iter->iter1;
  126. secondary = &iter->iter0;
  127. }
  128. if (selection & ITER_SKIP_SECONDARY) {
  129. if ((ok = ref_iterator_advance(*secondary)) != ITER_OK) {
  130. *secondary = NULL;
  131. if (ok == ITER_ERROR)
  132. goto error;
  133. }
  134. }
  135. if (selection & ITER_YIELD_CURRENT) {
  136. iter->base.refname = (*iter->current)->refname;
  137. iter->base.oid = (*iter->current)->oid;
  138. iter->base.flags = (*iter->current)->flags;
  139. return ITER_OK;
  140. }
  141. }
  142. error:
  143. ref_iterator_abort(ref_iterator);
  144. return ITER_ERROR;
  145. }
  146. static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,
  147. struct object_id *peeled)
  148. {
  149. struct merge_ref_iterator *iter =
  150. (struct merge_ref_iterator *)ref_iterator;
  151. if (!iter->current) {
  152. BUG("peel called before advance for merge iterator");
  153. }
  154. return ref_iterator_peel(*iter->current, peeled);
  155. }
  156. static int merge_ref_iterator_abort(struct ref_iterator *ref_iterator)
  157. {
  158. struct merge_ref_iterator *iter =
  159. (struct merge_ref_iterator *)ref_iterator;
  160. int ok = ITER_DONE;
  161. if (iter->iter0) {
  162. if (ref_iterator_abort(iter->iter0) != ITER_DONE)
  163. ok = ITER_ERROR;
  164. }
  165. if (iter->iter1) {
  166. if (ref_iterator_abort(iter->iter1) != ITER_DONE)
  167. ok = ITER_ERROR;
  168. }
  169. base_ref_iterator_free(ref_iterator);
  170. return ok;
  171. }
  172. static struct ref_iterator_vtable merge_ref_iterator_vtable = {
  173. merge_ref_iterator_advance,
  174. merge_ref_iterator_peel,
  175. merge_ref_iterator_abort
  176. };
  177. struct ref_iterator *merge_ref_iterator_begin(
  178. int ordered,
  179. struct ref_iterator *iter0, struct ref_iterator *iter1,
  180. ref_iterator_select_fn *select, void *cb_data)
  181. {
  182. struct merge_ref_iterator *iter = xcalloc(1, sizeof(*iter));
  183. struct ref_iterator *ref_iterator = &iter->base;
  184. /*
  185. * We can't do the same kind of is_empty_ref_iterator()-style
  186. * optimization here as overlay_ref_iterator_begin() does,
  187. * because we don't know the semantics of the select function.
  188. * It might, for example, implement "intersect" by passing
  189. * references through only if they exist in both iterators.
  190. */
  191. base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable, ordered);
  192. iter->iter0 = iter0;
  193. iter->iter1 = iter1;
  194. iter->select = select;
  195. iter->cb_data = cb_data;
  196. iter->current = NULL;
  197. return ref_iterator;
  198. }
  199. /*
  200. * A ref_iterator_select_fn that overlays the items from front on top
  201. * of those from back (like loose refs over packed refs). See
  202. * overlay_ref_iterator_begin().
  203. */
  204. static enum iterator_selection overlay_iterator_select(
  205. struct ref_iterator *front, struct ref_iterator *back,
  206. void *cb_data)
  207. {
  208. int cmp;
  209. if (!back)
  210. return front ? ITER_SELECT_0 : ITER_SELECT_DONE;
  211. else if (!front)
  212. return ITER_SELECT_1;
  213. cmp = strcmp(front->refname, back->refname);
  214. if (cmp < 0)
  215. return ITER_SELECT_0;
  216. else if (cmp > 0)
  217. return ITER_SELECT_1;
  218. else
  219. return ITER_SELECT_0_SKIP_1;
  220. }
  221. struct ref_iterator *overlay_ref_iterator_begin(
  222. struct ref_iterator *front, struct ref_iterator *back)
  223. {
  224. /*
  225. * Optimization: if one of the iterators is empty, return the
  226. * other one rather than incurring the overhead of wrapping
  227. * them.
  228. */
  229. if (is_empty_ref_iterator(front)) {
  230. ref_iterator_abort(front);
  231. return back;
  232. } else if (is_empty_ref_iterator(back)) {
  233. ref_iterator_abort(back);
  234. return front;
  235. } else if (!front->ordered || !back->ordered) {
  236. BUG("overlay_ref_iterator requires ordered inputs");
  237. }
  238. return merge_ref_iterator_begin(1, front, back,
  239. overlay_iterator_select, NULL);
  240. }
  241. struct prefix_ref_iterator {
  242. struct ref_iterator base;
  243. struct ref_iterator *iter0;
  244. char *prefix;
  245. int trim;
  246. };
  247. /* Return -1, 0, 1 if refname is before, inside, or after the prefix. */
  248. static int compare_prefix(const char *refname, const char *prefix)
  249. {
  250. while (*prefix) {
  251. if (*refname != *prefix)
  252. return ((unsigned char)*refname < (unsigned char)*prefix) ? -1 : +1;
  253. refname++;
  254. prefix++;
  255. }
  256. return 0;
  257. }
  258. static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
  259. {
  260. struct prefix_ref_iterator *iter =
  261. (struct prefix_ref_iterator *)ref_iterator;
  262. int ok;
  263. while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
  264. int cmp = compare_prefix(iter->iter0->refname, iter->prefix);
  265. if (cmp < 0)
  266. continue;
  267. if (cmp > 0) {
  268. /*
  269. * If the source iterator is ordered, then we
  270. * can stop the iteration as soon as we see a
  271. * refname that comes after the prefix:
  272. */
  273. if (iter->iter0->ordered) {
  274. ok = ref_iterator_abort(iter->iter0);
  275. break;
  276. } else {
  277. continue;
  278. }
  279. }
  280. if (iter->trim) {
  281. /*
  282. * It is nonsense to trim off characters that
  283. * you haven't already checked for via a
  284. * prefix check, whether via this
  285. * `prefix_ref_iterator` or upstream in
  286. * `iter0`). So if there wouldn't be at least
  287. * one character left in the refname after
  288. * trimming, report it as a bug:
  289. */
  290. if (strlen(iter->iter0->refname) <= iter->trim)
  291. BUG("attempt to trim too many characters");
  292. iter->base.refname = iter->iter0->refname + iter->trim;
  293. } else {
  294. iter->base.refname = iter->iter0->refname;
  295. }
  296. iter->base.oid = iter->iter0->oid;
  297. iter->base.flags = iter->iter0->flags;
  298. return ITER_OK;
  299. }
  300. iter->iter0 = NULL;
  301. if (ref_iterator_abort(ref_iterator) != ITER_DONE)
  302. return ITER_ERROR;
  303. return ok;
  304. }
  305. static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator,
  306. struct object_id *peeled)
  307. {
  308. struct prefix_ref_iterator *iter =
  309. (struct prefix_ref_iterator *)ref_iterator;
  310. return ref_iterator_peel(iter->iter0, peeled);
  311. }
  312. static int prefix_ref_iterator_abort(struct ref_iterator *ref_iterator)
  313. {
  314. struct prefix_ref_iterator *iter =
  315. (struct prefix_ref_iterator *)ref_iterator;
  316. int ok = ITER_DONE;
  317. if (iter->iter0)
  318. ok = ref_iterator_abort(iter->iter0);
  319. free(iter->prefix);
  320. base_ref_iterator_free(ref_iterator);
  321. return ok;
  322. }
  323. static struct ref_iterator_vtable prefix_ref_iterator_vtable = {
  324. prefix_ref_iterator_advance,
  325. prefix_ref_iterator_peel,
  326. prefix_ref_iterator_abort
  327. };
  328. struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
  329. const char *prefix,
  330. int trim)
  331. {
  332. struct prefix_ref_iterator *iter;
  333. struct ref_iterator *ref_iterator;
  334. if (!*prefix && !trim)
  335. return iter0; /* optimization: no need to wrap iterator */
  336. iter = xcalloc(1, sizeof(*iter));
  337. ref_iterator = &iter->base;
  338. base_ref_iterator_init(ref_iterator, &prefix_ref_iterator_vtable, iter0->ordered);
  339. iter->iter0 = iter0;
  340. iter->prefix = xstrdup(prefix);
  341. iter->trim = trim;
  342. return ref_iterator;
  343. }
  344. struct ref_iterator *current_ref_iter = NULL;
  345. int do_for_each_ref_iterator(struct ref_iterator *iter,
  346. each_ref_fn fn, void *cb_data)
  347. {
  348. int retval = 0, ok;
  349. struct ref_iterator *old_ref_iter = current_ref_iter;
  350. current_ref_iter = iter;
  351. while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
  352. retval = fn(iter->refname, iter->oid, iter->flags, cb_data);
  353. if (retval) {
  354. /*
  355. * If ref_iterator_abort() returns ITER_ERROR,
  356. * we ignore that error in deference to the
  357. * callback function's return value.
  358. */
  359. ref_iterator_abort(iter);
  360. goto out;
  361. }
  362. }
  363. out:
  364. current_ref_iter = old_ref_iter;
  365. if (ok == ITER_ERROR)
  366. return -1;
  367. return retval;
  368. }