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.

114 lines
2.6KB

  1. #include "cache.h"
  2. #include "repository.h"
  3. #include "refs.h"
  4. #include "remote.h"
  5. #include "argv-array.h"
  6. #include "ls-refs.h"
  7. #include "pkt-line.h"
  8. #include "config.h"
  9. /*
  10. * Check if one of the prefixes is a prefix of the ref.
  11. * If no prefixes were provided, all refs match.
  12. */
  13. static int ref_match(const struct argv_array *prefixes, const char *refname)
  14. {
  15. int i;
  16. if (!prefixes->argc)
  17. return 1; /* no restriction */
  18. for (i = 0; i < prefixes->argc; i++) {
  19. const char *prefix = prefixes->argv[i];
  20. if (starts_with(refname, prefix))
  21. return 1;
  22. }
  23. return 0;
  24. }
  25. struct ls_refs_data {
  26. unsigned peel;
  27. unsigned symrefs;
  28. struct argv_array prefixes;
  29. };
  30. static int send_ref(const char *refname, const struct object_id *oid,
  31. int flag, void *cb_data)
  32. {
  33. struct ls_refs_data *data = cb_data;
  34. const char *refname_nons = strip_namespace(refname);
  35. struct strbuf refline = STRBUF_INIT;
  36. if (ref_is_hidden(refname_nons, refname))
  37. return 0;
  38. if (!ref_match(&data->prefixes, refname_nons))
  39. return 0;
  40. strbuf_addf(&refline, "%s %s", oid_to_hex(oid), refname_nons);
  41. if (data->symrefs && flag & REF_ISSYMREF) {
  42. struct object_id unused;
  43. const char *symref_target = resolve_ref_unsafe(refname, 0,
  44. &unused,
  45. &flag);
  46. if (!symref_target)
  47. die("'%s' is a symref but it is not?", refname);
  48. strbuf_addf(&refline, " symref-target:%s",
  49. strip_namespace(symref_target));
  50. }
  51. if (data->peel) {
  52. struct object_id peeled;
  53. if (!peel_ref(refname, &peeled))
  54. strbuf_addf(&refline, " peeled:%s", oid_to_hex(&peeled));
  55. }
  56. strbuf_addch(&refline, '\n');
  57. packet_write(1, refline.buf, refline.len);
  58. strbuf_release(&refline);
  59. return 0;
  60. }
  61. static int ls_refs_config(const char *var, const char *value, void *data)
  62. {
  63. /*
  64. * We only serve fetches over v2 for now, so respect only "uploadpack"
  65. * config. This may need to eventually be expanded to "receive", but we
  66. * don't yet know how that information will be passed to ls-refs.
  67. */
  68. return parse_hide_refs_config(var, value, "uploadpack");
  69. }
  70. int ls_refs(struct repository *r, struct argv_array *keys,
  71. struct packet_reader *request)
  72. {
  73. struct ls_refs_data data;
  74. memset(&data, 0, sizeof(data));
  75. git_config(ls_refs_config, NULL);
  76. while (packet_reader_read(request) != PACKET_READ_FLUSH) {
  77. const char *arg = request->line;
  78. const char *out;
  79. if (!strcmp("peel", arg))
  80. data.peel = 1;
  81. else if (!strcmp("symrefs", arg))
  82. data.symrefs = 1;
  83. else if (skip_prefix(arg, "ref-prefix ", &out))
  84. argv_array_push(&data.prefixes, out);
  85. }
  86. head_ref_namespaced(send_ref, &data);
  87. for_each_namespaced_ref(send_ref, &data);
  88. packet_flush(1);
  89. argv_array_clear(&data.prefixes);
  90. return 0;
  91. }