2727#include "promisor-remote.h"
2828#include "mailmap.h"
2929#include "write-or-die.h"
30+ #include "alias.h"
31+ #include "remote.h"
32+ #include "transport.h"
33+
34+ /* Maximum length for a remote URL. While no universal standard exists,
35+ * 8K is assumed to be a reasonable limit.
36+ */
37+ #define MAX_REMOTE_URL_LEN (8*1024)
38+ /* Maximum number of objects allowed in a single remote-object-info request. */
39+ #define MAX_ALLOWED_OBJ_LIMIT 10000
40+ /* Maximum input size permitted for the remote-object-info command. */
41+ #define MAX_REMOTE_OBJ_INFO_LINE (MAX_REMOTE_URL_LEN + MAX_ALLOWED_OBJ_LIMIT * (GIT_MAX_HEXSZ + 1))
3042
3143enum batch_mode {
3244 BATCH_MODE_CONTENTS ,
@@ -48,6 +60,8 @@ struct batch_options {
4860};
4961
5062static const char * force_path ;
63+ static struct object_info * remote_object_info ;
64+ static struct oid_array object_info_oids = OID_ARRAY_INIT ;
5165
5266static struct string_list mailmap = STRING_LIST_INIT_NODUP ;
5367static int use_mailmap ;
@@ -579,6 +593,61 @@ static void batch_one_object(const char *obj_name,
579593 object_context_release (& ctx );
580594}
581595
596+ static int get_remote_info (struct batch_options * opt , int argc , const char * * argv )
597+ {
598+ int retval = 0 ;
599+ struct remote * remote = NULL ;
600+ struct object_id oid ;
601+ struct string_list object_info_options = STRING_LIST_INIT_NODUP ;
602+ static struct transport * gtransport ;
603+
604+ /*
605+ * Change the format to "%(objectname) %(objectsize)" when
606+ * remote-object-info command is used. Once we start supporting objecttype
607+ * the default format should change to DEFAULT_FORMAT.
608+ */
609+ if (!opt -> format )
610+ opt -> format = "%(objectname) %(objectsize)" ;
611+
612+ remote = remote_get (argv [0 ]);
613+ if (!remote )
614+ die (_ ("must supply valid remote when using remote-object-info" ));
615+
616+ oid_array_clear (& object_info_oids );
617+ for (size_t i = 1 ; i < argc ; i ++ ) {
618+ if (get_oid_hex (argv [i ], & oid ))
619+ die (_ ("Not a valid object name %s" ), argv [i ]);
620+ oid_array_append (& object_info_oids , & oid );
621+ }
622+ if (!object_info_oids .nr )
623+ die (_ ("remote-object-info requires objects" ));
624+
625+ gtransport = transport_get (remote , NULL );
626+ if (gtransport -> smart_options ) {
627+ CALLOC_ARRAY (remote_object_info , object_info_oids .nr );
628+ gtransport -> smart_options -> object_info = 1 ;
629+ gtransport -> smart_options -> object_info_oids = & object_info_oids ;
630+
631+ /* 'objectsize' is the only option currently supported */
632+ if (!strstr (opt -> format , "%(objectsize)" ))
633+ die (_ ("%s is currently not supported with remote-object-info" ), opt -> format );
634+
635+ string_list_append (& object_info_options , "size" );
636+
637+ if (object_info_options .nr > 0 ) {
638+ gtransport -> smart_options -> object_info_options = & object_info_options ;
639+ gtransport -> smart_options -> object_info_data = remote_object_info ;
640+ retval = transport_fetch_refs (gtransport , NULL );
641+ }
642+ } else {
643+ retval = -1 ;
644+ }
645+
646+ string_list_clear (& object_info_options , 0 );
647+ transport_disconnect (gtransport );
648+ return retval ;
649+ }
650+
582651struct object_cb_data {
583652 struct batch_options * opt ;
584653 struct expand_data * expand ;
@@ -670,28 +739,68 @@ static void parse_cmd_info(struct batch_options *opt,
670739 batch_one_object (line , output , opt , data );
671740}
672741
742+ static void parse_cmd_remote_object_info (struct batch_options * opt ,
743+ const char * line , struct strbuf * output ,
744+ struct expand_data * data )
745+ {
746+ int count ;
747+ const char * * argv ;
748+ char * line_to_split ;
749+
750+ if (strlen (line ) >= MAX_REMOTE_OBJ_INFO_LINE )
751+ die (_ ("remote-object-info command input overflow "
752+ "(no more than %d objects are allowed)" ),
753+ MAX_ALLOWED_OBJ_LIMIT );
754+
755+ line_to_split = xstrdup (line );
756+ count = split_cmdline (line_to_split , & argv );
757+ if (count < 0 )
758+ die (_ ("split remote-object-info command" ));
759+
760+ if (get_remote_info (opt , count , argv ))
761+ goto cleanup ;
762+
763+ data -> skip_object_info = 1 ;
764+ for (size_t i = 0 ; i < object_info_oids .nr ; i ++ ) {
765+ data -> oid = object_info_oids .oid [i ];
766+ if (remote_object_info [i ].sizep ) {
767+ /*
768+ * When reaching here, it means remote-object-info can retrieve
769+ * information from server without downloading them.
770+ */
771+ data -> size = * remote_object_info [i ].sizep ;
772+ opt -> batch_mode = BATCH_MODE_INFO ;
773+ batch_object_write (argv [i + 1 ], output , opt , data , NULL , 0 );
774+ }
775+ }
776+ data -> skip_object_info = 0 ;
777+
778+ cleanup :
779+ for (size_t i = 0 ; i < object_info_oids .nr ; i ++ )
780+ free_object_info_contents (& remote_object_info [i ]);
781+ free (line_to_split );
782+ free (argv );
783+ free (remote_object_info );
784+ }
785+
673786static void dispatch_calls (struct batch_options * opt ,
674787 struct strbuf * output ,
675788 struct expand_data * data ,
676789 struct queued_cmd * cmd ,
677790 int nr )
678791{
679- int i ;
680-
681792 if (!opt -> buffer_output )
682793 die (_ ("flush is only for --buffer mode" ));
683794
684- for (i = 0 ; i < nr ; i ++ )
795+ for (size_t i = 0 ; i < nr ; i ++ )
685796 cmd [i ].fn (opt , cmd [i ].line , output , data );
686797
687798 fflush (stdout );
688799}
689800
690801static void free_cmds (struct queued_cmd * cmd , size_t * nr )
691802{
692- size_t i ;
693-
694- for (i = 0 ; i < * nr ; i ++ )
803+ for (size_t i = 0 ; i < * nr ; i ++ )
695804 FREE_AND_NULL (cmd [i ].line );
696805
697806 * nr = 0 ;
@@ -705,6 +814,7 @@ static const struct parse_cmd {
705814} commands [] = {
706815 { "contents" , parse_cmd_contents , 1 },
707816 { "info" , parse_cmd_info , 1 },
817+ { "remote-object-info" , parse_cmd_remote_object_info , 1 },
708818 { "flush" , NULL , 0 },
709819};
710820
@@ -717,7 +827,6 @@ static void batch_objects_command(struct batch_options *opt,
717827 size_t alloc = 0 , nr = 0 ;
718828
719829 while (strbuf_getdelim_strip_crlf (& input , stdin , opt -> input_delim ) != EOF ) {
720- int i ;
721830 const struct parse_cmd * cmd = NULL ;
722831 const char * p = NULL , * cmd_end ;
723832 struct queued_cmd call = {0 };
@@ -727,7 +836,7 @@ static void batch_objects_command(struct batch_options *opt,
727836 if (isspace (* input .buf ))
728837 die (_ ("whitespace before command: '%s'" ), input .buf );
729838
730- for (i = 0 ; i < ARRAY_SIZE (commands ); i ++ ) {
839+ for (size_t i = 0 ; i < ARRAY_SIZE (commands ); i ++ ) {
731840 if (!skip_prefix (input .buf , commands [i ].name , & cmd_end ))
732841 continue ;
733842
0 commit comments