|
29 | 29 | #include "promisor-remote.h" |
30 | 30 | #include "mailmap.h" |
31 | 31 | #include "write-or-die.h" |
| 32 | +#include "alias.h" |
| 33 | +#include "remote.h" |
| 34 | +#include "transport.h" |
| 35 | + |
| 36 | +/* |
| 37 | + * Maximum length for a remote URL. While no universal standard exists, |
| 38 | + * 8K is assumed to be a reasonable limit. |
| 39 | + */ |
| 40 | +#define MAX_REMOTE_URL_LEN (8 * 1024) |
| 41 | + |
| 42 | +/* Maximum number of objects allowed in a single remote-object-info request. */ |
| 43 | +#define MAX_ALLOWED_OBJ_LIMIT 10000 |
| 44 | + |
| 45 | +/* Maximum input size permitted for the remote-object-info command. */ |
| 46 | +#define MAX_REMOTE_OBJ_INFO_LINE \ |
| 47 | + (MAX_REMOTE_URL_LEN + MAX_ALLOWED_OBJ_LIMIT * (GIT_MAX_HEXSZ + 1)) |
32 | 48 |
|
33 | 49 | enum batch_mode { |
34 | 50 | BATCH_MODE_CONTENTS, |
@@ -638,6 +654,80 @@ static void batch_one_object(const char *obj_name, |
638 | 654 | object_context_release(&ctx); |
639 | 655 | } |
640 | 656 |
|
| 657 | +static int get_remote_info(struct batch_options *opt, |
| 658 | + int argc, |
| 659 | + const char **argv, |
| 660 | + struct object_info **remote_object_info, |
| 661 | + struct oid_array *object_info_oids) |
| 662 | +{ |
| 663 | + int retval = 0; |
| 664 | + struct remote *remote = NULL; |
| 665 | + struct object_id oid; |
| 666 | + struct string_list object_info_options = STRING_LIST_INIT_NODUP; |
| 667 | + struct transport *gtransport; |
| 668 | + |
| 669 | + /* |
| 670 | + * TODO: Change the format to "%(objectname) %(objectsize)" when |
| 671 | + * remote-object-info command is used. Once we start supporting objecttype |
| 672 | + * the default format should change to DEFAULT_FORMAT. |
| 673 | + */ |
| 674 | + if (!opt->format) |
| 675 | + opt->format = "%(objectname) %(objectsize)"; |
| 676 | + |
| 677 | + remote = remote_get(argv[0]); |
| 678 | + if (!remote) |
| 679 | + die(_("must supply valid remote when using remote-object-info")); |
| 680 | + |
| 681 | + oid_array_clear(object_info_oids); |
| 682 | + for (size_t i = 1; i < argc; i++) { |
| 683 | + if (get_oid_hex(argv[i], &oid)) { |
| 684 | + size_t len = strlen(argv[i]); |
| 685 | + |
| 686 | + if (len < the_hash_algo->hexsz && len >= 4) { |
| 687 | + size_t j; |
| 688 | + for (j = 0; j < len; j++) |
| 689 | + if (!isxdigit(argv[i][j])) |
| 690 | + break; |
| 691 | + if (j == len) |
| 692 | + die(_("remote-object-info does not support " |
| 693 | + "short oids, %d characters required"), |
| 694 | + (int)the_hash_algo->hexsz); |
| 695 | + } |
| 696 | + die(_("not a valid object name '%s'"), argv[i]); |
| 697 | + } |
| 698 | + oid_array_append(object_info_oids, &oid); |
| 699 | + } |
| 700 | + |
| 701 | + if (!object_info_oids->nr) |
| 702 | + die(_("remote-object-info requires objects")); |
| 703 | + |
| 704 | + gtransport = transport_get(remote, NULL); |
| 705 | + |
| 706 | + if (!gtransport->smart_options) { |
| 707 | + retval = -1; |
| 708 | + goto cleanup; |
| 709 | + } |
| 710 | + |
| 711 | + CALLOC_ARRAY(*remote_object_info, object_info_oids->nr); |
| 712 | + gtransport->smart_options->object_info_oids = object_info_oids; |
| 713 | + |
| 714 | + /* 'objectsize' is the only option currently supported */ |
| 715 | + if (!strstr(opt->format, "%(objectsize)")) |
| 716 | + die(_("%s is currently not supported with remote-object-info"), opt->format); |
| 717 | + |
| 718 | + string_list_append(&object_info_options, "size"); |
| 719 | + |
| 720 | + if (object_info_options.nr > 0) { |
| 721 | + gtransport->smart_options->object_info_options = &object_info_options; |
| 722 | + gtransport->smart_options->object_info_data = *remote_object_info; |
| 723 | + retval = transport_fetch_object_info(gtransport); |
| 724 | + } |
| 725 | +cleanup: |
| 726 | + string_list_clear(&object_info_options, 0); |
| 727 | + transport_disconnect(gtransport); |
| 728 | + return retval; |
| 729 | +} |
| 730 | + |
641 | 731 | struct object_cb_data { |
642 | 732 | struct batch_options *opt; |
643 | 733 | struct expand_data *expand; |
@@ -719,6 +809,57 @@ static void parse_cmd_mailmap(struct batch_options *opt UNUSED, |
719 | 809 | load_mailmap(); |
720 | 810 | } |
721 | 811 |
|
| 812 | +static void parse_cmd_remote_object_info(struct batch_options *opt, |
| 813 | + const char *line, struct strbuf *output, |
| 814 | + struct expand_data *data) |
| 815 | +{ |
| 816 | + int count; |
| 817 | + const char **argv; |
| 818 | + char *line_to_split; |
| 819 | + struct object_info *remote_object_info = NULL; |
| 820 | + struct oid_array object_info_oids = OID_ARRAY_INIT; |
| 821 | + |
| 822 | + if (strlen(line) >= MAX_REMOTE_OBJ_INFO_LINE) |
| 823 | + die(_("remote-object-info command too long")); |
| 824 | + |
| 825 | + line_to_split = xstrdup(line); |
| 826 | + count = split_cmdline(line_to_split, &argv); |
| 827 | + if (count < 0) |
| 828 | + die(_("remote-object-info: %s"), split_cmdline_strerror(count)); |
| 829 | + if (count - 1 > MAX_ALLOWED_OBJ_LIMIT) |
| 830 | + die(_("remote-object-info supports at most %d objects"), |
| 831 | + MAX_ALLOWED_OBJ_LIMIT); |
| 832 | + |
| 833 | + if (get_remote_info(opt, count, argv, &remote_object_info, |
| 834 | + &object_info_oids)) |
| 835 | + goto cleanup; |
| 836 | + |
| 837 | + data->skip_object_info = 1; |
| 838 | + for (size_t i = 0; i < object_info_oids.nr; i++) { |
| 839 | + data->oid = object_info_oids.oid[i]; |
| 840 | + if (remote_object_info[i].sizep) { |
| 841 | + /* |
| 842 | + * When reaching here, it means remote-object-info can retrieve |
| 843 | + * information from server without downloading them. |
| 844 | + */ |
| 845 | + data->size = *remote_object_info[i].sizep; |
| 846 | + opt->batch_mode = BATCH_MODE_INFO; |
| 847 | + batch_object_write(argv[i + 1], output, opt, data, NULL, 0); |
| 848 | + } else { |
| 849 | + report_object_status(opt, oid_to_hex(&data->oid), &data->oid, "missing"); |
| 850 | + } |
| 851 | + } |
| 852 | + data->skip_object_info = 0; |
| 853 | + |
| 854 | +cleanup: |
| 855 | + for (size_t i = 0; i < object_info_oids.nr; i++) |
| 856 | + free_object_info_contents(&remote_object_info[i]); |
| 857 | + free(line_to_split); |
| 858 | + free(argv); |
| 859 | + free(remote_object_info); |
| 860 | + oid_array_clear(&object_info_oids); |
| 861 | +} |
| 862 | + |
722 | 863 | static void dispatch_calls(struct batch_options *opt, |
723 | 864 | struct strbuf *output, |
724 | 865 | struct expand_data *data, |
@@ -750,8 +891,9 @@ static const struct parse_cmd { |
750 | 891 | } commands[] = { |
751 | 892 | { "contents", parse_cmd_contents, 1 }, |
752 | 893 | { "info", parse_cmd_info, 1 }, |
753 | | - { "flush", NULL, 0 }, |
754 | 894 | { "mailmap", parse_cmd_mailmap, 1 }, |
| 895 | + { "remote-object-info", parse_cmd_remote_object_info, 1 }, |
| 896 | + { "flush", NULL, 0 }, |
755 | 897 | }; |
756 | 898 |
|
757 | 899 | static void batch_objects_command(struct batch_options *opt, |
|
0 commit comments