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.

269 lines
5.6KB

  1. #include "cache.h"
  2. #include "object-store.h"
  3. #include "promisor-remote.h"
  4. #include "config.h"
  5. #include "transport.h"
  6. static char *repository_format_partial_clone;
  7. static const char *core_partial_clone_filter_default;
  8. void set_repository_format_partial_clone(char *partial_clone)
  9. {
  10. repository_format_partial_clone = xstrdup_or_null(partial_clone);
  11. }
  12. static int fetch_refs(const char *remote_name, struct ref *ref)
  13. {
  14. struct remote *remote;
  15. struct transport *transport;
  16. int original_fetch_if_missing = fetch_if_missing;
  17. int res;
  18. fetch_if_missing = 0;
  19. remote = remote_get(remote_name);
  20. if (!remote->url[0])
  21. die(_("Remote with no URL"));
  22. transport = transport_get(remote, remote->url[0]);
  23. transport_set_option(transport, TRANS_OPT_FROM_PROMISOR, "1");
  24. transport_set_option(transport, TRANS_OPT_NO_DEPENDENTS, "1");
  25. res = transport_fetch_refs(transport, ref);
  26. fetch_if_missing = original_fetch_if_missing;
  27. return res;
  28. }
  29. static int fetch_objects(const char *remote_name,
  30. const struct object_id *oids,
  31. int oid_nr)
  32. {
  33. struct ref *ref = NULL;
  34. int i;
  35. for (i = 0; i < oid_nr; i++) {
  36. struct ref *new_ref = alloc_ref(oid_to_hex(&oids[i]));
  37. oidcpy(&new_ref->old_oid, &oids[i]);
  38. new_ref->exact_oid = 1;
  39. new_ref->next = ref;
  40. ref = new_ref;
  41. }
  42. return fetch_refs(remote_name, ref);
  43. }
  44. static struct promisor_remote *promisors;
  45. static struct promisor_remote **promisors_tail = &promisors;
  46. static struct promisor_remote *promisor_remote_new(const char *remote_name)
  47. {
  48. struct promisor_remote *r;
  49. if (*remote_name == '/') {
  50. warning(_("promisor remote name cannot begin with '/': %s"),
  51. remote_name);
  52. return NULL;
  53. }
  54. FLEX_ALLOC_STR(r, name, remote_name);
  55. *promisors_tail = r;
  56. promisors_tail = &r->next;
  57. return r;
  58. }
  59. static struct promisor_remote *promisor_remote_lookup(const char *remote_name,
  60. struct promisor_remote **previous)
  61. {
  62. struct promisor_remote *r, *p;
  63. for (p = NULL, r = promisors; r; p = r, r = r->next)
  64. if (!strcmp(r->name, remote_name)) {
  65. if (previous)
  66. *previous = p;
  67. return r;
  68. }
  69. return NULL;
  70. }
  71. static void promisor_remote_move_to_tail(struct promisor_remote *r,
  72. struct promisor_remote *previous)
  73. {
  74. if (r->next == NULL)
  75. return;
  76. if (previous)
  77. previous->next = r->next;
  78. else
  79. promisors = r->next ? r->next : r;
  80. r->next = NULL;
  81. *promisors_tail = r;
  82. promisors_tail = &r->next;
  83. }
  84. static int promisor_remote_config(const char *var, const char *value, void *data)
  85. {
  86. const char *name;
  87. int namelen;
  88. const char *subkey;
  89. if (!strcmp(var, "core.partialclonefilter"))
  90. return git_config_string(&core_partial_clone_filter_default,
  91. var, value);
  92. if (parse_config_key(var, "remote", &name, &namelen, &subkey) < 0)
  93. return 0;
  94. if (!strcmp(subkey, "promisor")) {
  95. char *remote_name;
  96. if (!git_config_bool(var, value))
  97. return 0;
  98. remote_name = xmemdupz(name, namelen);
  99. if (!promisor_remote_lookup(remote_name, NULL))
  100. promisor_remote_new(remote_name);
  101. free(remote_name);
  102. return 0;
  103. }
  104. if (!strcmp(subkey, "partialclonefilter")) {
  105. struct promisor_remote *r;
  106. char *remote_name = xmemdupz(name, namelen);
  107. r = promisor_remote_lookup(remote_name, NULL);
  108. if (!r)
  109. r = promisor_remote_new(remote_name);
  110. free(remote_name);
  111. if (!r)
  112. return 0;
  113. return git_config_string(&r->partial_clone_filter, var, value);
  114. }
  115. return 0;
  116. }
  117. static int initialized;
  118. static void promisor_remote_init(void)
  119. {
  120. if (initialized)
  121. return;
  122. initialized = 1;
  123. git_config(promisor_remote_config, NULL);
  124. if (repository_format_partial_clone) {
  125. struct promisor_remote *o, *previous;
  126. o = promisor_remote_lookup(repository_format_partial_clone,
  127. &previous);
  128. if (o)
  129. promisor_remote_move_to_tail(o, previous);
  130. else
  131. promisor_remote_new(repository_format_partial_clone);
  132. }
  133. }
  134. static void promisor_remote_clear(void)
  135. {
  136. while (promisors) {
  137. struct promisor_remote *r = promisors;
  138. promisors = promisors->next;
  139. free(r);
  140. }
  141. promisors_tail = &promisors;
  142. }
  143. void promisor_remote_reinit(void)
  144. {
  145. initialized = 0;
  146. promisor_remote_clear();
  147. promisor_remote_init();
  148. }
  149. struct promisor_remote *promisor_remote_find(const char *remote_name)
  150. {
  151. promisor_remote_init();
  152. if (!remote_name)
  153. return promisors;
  154. return promisor_remote_lookup(remote_name, NULL);
  155. }
  156. int has_promisor_remote(void)
  157. {
  158. return !!promisor_remote_find(NULL);
  159. }
  160. static int remove_fetched_oids(struct repository *repo,
  161. struct object_id **oids,
  162. int oid_nr, int to_free)
  163. {
  164. int i, remaining_nr = 0;
  165. int *remaining = xcalloc(oid_nr, sizeof(*remaining));
  166. struct object_id *old_oids = *oids;
  167. struct object_id *new_oids;
  168. for (i = 0; i < oid_nr; i++)
  169. if (oid_object_info_extended(repo, &old_oids[i], NULL,
  170. OBJECT_INFO_SKIP_FETCH_OBJECT)) {
  171. remaining[i] = 1;
  172. remaining_nr++;
  173. }
  174. if (remaining_nr) {
  175. int j = 0;
  176. new_oids = xcalloc(remaining_nr, sizeof(*new_oids));
  177. for (i = 0; i < oid_nr; i++)
  178. if (remaining[i])
  179. oidcpy(&new_oids[j++], &old_oids[i]);
  180. *oids = new_oids;
  181. if (to_free)
  182. free(old_oids);
  183. }
  184. free(remaining);
  185. return remaining_nr;
  186. }
  187. int promisor_remote_get_direct(struct repository *repo,
  188. const struct object_id *oids,
  189. int oid_nr)
  190. {
  191. struct promisor_remote *r;
  192. struct object_id *remaining_oids = (struct object_id *)oids;
  193. int remaining_nr = oid_nr;
  194. int to_free = 0;
  195. int res = -1;
  196. promisor_remote_init();
  197. for (r = promisors; r; r = r->next) {
  198. if (fetch_objects(r->name, remaining_oids, remaining_nr) < 0) {
  199. if (remaining_nr == 1)
  200. continue;
  201. remaining_nr = remove_fetched_oids(repo, &remaining_oids,
  202. remaining_nr, to_free);
  203. if (remaining_nr) {
  204. to_free = 1;
  205. continue;
  206. }
  207. }
  208. res = 0;
  209. break;
  210. }
  211. if (to_free)
  212. free(remaining_oids);
  213. return res;
  214. }