2929#include "promisor-remote.h"
3030#include "mailmap.h"
3131#include "write-or-die.h"
32+ #include "alias.h"
33+ #include "remote.h"
34+ #include "transport.h"
35+
36+ /* Maximum length for a remote URL. While no universal standard exists,
37+ * 8K is assumed to be a reasonable limit.
38+ */
39+ #define MAX_REMOTE_URL_LEN (8*1024)
40+ /* Maximum number of objects allowed in a single remote-object-info request. */
41+ #define MAX_ALLOWED_OBJ_LIMIT 10000
42+ /* Maximum input size permitted for the remote-object-info command. */
43+ #define MAX_REMOTE_OBJ_INFO_LINE (MAX_REMOTE_URL_LEN + MAX_ALLOWED_OBJ_LIMIT * (GIT_MAX_HEXSZ + 1))
3244
3345enum batch_mode {
3446 BATCH_MODE_CONTENTS ,
@@ -51,6 +63,8 @@ struct batch_options {
5163};
5264
5365static const char * force_path ;
66+ static struct object_info * remote_object_info ;
67+ static struct oid_array object_info_oids = OID_ARRAY_INIT ;
5468
5569static struct string_list mailmap = STRING_LIST_INIT_NODUP ;
5670static int use_mailmap ;
@@ -627,6 +641,61 @@ static void batch_one_object(const char *obj_name,
627641 object_context_release (& ctx );
628642}
629643
644+ static int get_remote_info (struct batch_options * opt , int argc , const char * * argv )
645+ {
646+ int retval = 0 ;
647+ struct remote * remote = NULL ;
648+ struct object_id oid ;
649+ struct string_list object_info_options = STRING_LIST_INIT_NODUP ;
650+ static struct transport * gtransport ;
651+
652+ /*
653+ * Change the format to "%(objectname) %(objectsize)" when
654+ * remote-object-info command is used. Once we start supporting objecttype
655+ * the default format should change to DEFAULT_FORMAT.
656+ */
657+ if (!opt -> format )
658+ opt -> format = "%(objectname) %(objectsize)" ;
659+
660+ remote = remote_get (argv [0 ]);
661+ if (!remote )
662+ die (_ ("must supply valid remote when using remote-object-info" ));
663+
664+ oid_array_clear (& object_info_oids );
665+ for (size_t i = 1 ; i < argc ; i ++ ) {
666+ if (get_oid_hex (argv [i ], & oid ))
667+ die (_ ("Not a valid object name %s" ), argv [i ]);
668+ oid_array_append (& object_info_oids , & oid );
669+ }
670+ if (!object_info_oids .nr )
671+ die (_ ("remote-object-info requires objects" ));
672+
673+ gtransport = transport_get (remote , NULL );
674+ if (gtransport -> smart_options ) {
675+ CALLOC_ARRAY (remote_object_info , object_info_oids .nr );
676+ gtransport -> smart_options -> object_info = 1 ;
677+ gtransport -> smart_options -> object_info_oids = & object_info_oids ;
678+
679+ /* 'objectsize' is the only option currently supported */
680+ if (!strstr (opt -> format , "%(objectsize)" ))
681+ die (_ ("%s is currently not supported with remote-object-info" ), opt -> format );
682+
683+ string_list_append (& object_info_options , "size" );
684+
685+ if (object_info_options .nr > 0 ) {
686+ gtransport -> smart_options -> object_info_options = & object_info_options ;
687+ gtransport -> smart_options -> object_info_data = remote_object_info ;
688+ retval = transport_fetch_refs (gtransport , NULL );
689+ }
690+ } else {
691+ retval = -1 ;
692+ }
693+
694+ string_list_clear (& object_info_options , 0 );
695+ transport_disconnect (gtransport );
696+ return retval ;
697+ }
698+
630699struct object_cb_data {
631700 struct batch_options * opt ;
632701 struct expand_data * expand ;
@@ -694,28 +763,68 @@ static void parse_cmd_info(struct batch_options *opt,
694763 batch_one_object (line , output , opt , data );
695764}
696765
766+ static void parse_cmd_remote_object_info (struct batch_options * opt ,
767+ const char * line , struct strbuf * output ,
768+ struct expand_data * data )
769+ {
770+ int count ;
771+ const char * * argv ;
772+ char * line_to_split ;
773+
774+ if (strlen (line ) >= MAX_REMOTE_OBJ_INFO_LINE )
775+ die (_ ("remote-object-info command input overflow "
776+ "(no more than %d objects are allowed)" ),
777+ MAX_ALLOWED_OBJ_LIMIT );
778+
779+ line_to_split = xstrdup (line );
780+ count = split_cmdline (line_to_split , & argv );
781+ if (count < 0 )
782+ die (_ ("split remote-object-info command" ));
783+
784+ if (get_remote_info (opt , count , argv ))
785+ goto cleanup ;
786+
787+ data -> skip_object_info = 1 ;
788+ for (size_t i = 0 ; i < object_info_oids .nr ; i ++ ) {
789+ data -> oid = object_info_oids .oid [i ];
790+ if (remote_object_info [i ].sizep ) {
791+ /*
792+ * When reaching here, it means remote-object-info can retrieve
793+ * information from server without downloading them.
794+ */
795+ data -> size = * remote_object_info [i ].sizep ;
796+ opt -> batch_mode = BATCH_MODE_INFO ;
797+ batch_object_write (argv [i + 1 ], output , opt , data , NULL , 0 );
798+ }
799+ }
800+ data -> skip_object_info = 0 ;
801+
802+ cleanup :
803+ for (size_t i = 0 ; i < object_info_oids .nr ; i ++ )
804+ free_object_info_contents (& remote_object_info [i ]);
805+ free (line_to_split );
806+ free (argv );
807+ free (remote_object_info );
808+ }
809+
697810static void dispatch_calls (struct batch_options * opt ,
698811 struct strbuf * output ,
699812 struct expand_data * data ,
700813 struct queued_cmd * cmd ,
701814 int nr )
702815{
703- int i ;
704-
705816 if (!opt -> buffer_output )
706817 die (_ ("flush is only for --buffer mode" ));
707818
708- for (i = 0 ; i < nr ; i ++ )
819+ for (size_t i = 0 ; i < nr ; i ++ )
709820 cmd [i ].fn (opt , cmd [i ].line , output , data );
710821
711822 fflush (stdout );
712823}
713824
714825static void free_cmds (struct queued_cmd * cmd , size_t * nr )
715826{
716- size_t i ;
717-
718- for (i = 0 ; i < * nr ; i ++ )
827+ for (size_t i = 0 ; i < * nr ; i ++ )
719828 FREE_AND_NULL (cmd [i ].line );
720829
721830 * nr = 0 ;
@@ -729,6 +838,7 @@ static const struct parse_cmd {
729838} commands [] = {
730839 { "contents" , parse_cmd_contents , 1 },
731840 { "info" , parse_cmd_info , 1 },
841+ { "remote-object-info" , parse_cmd_remote_object_info , 1 },
732842 { "flush" , NULL , 0 },
733843};
734844
@@ -741,7 +851,6 @@ static void batch_objects_command(struct batch_options *opt,
741851 size_t alloc = 0 , nr = 0 ;
742852
743853 while (strbuf_getdelim_strip_crlf (& input , stdin , opt -> input_delim ) != EOF ) {
744- int i ;
745854 const struct parse_cmd * cmd = NULL ;
746855 const char * p = NULL , * cmd_end ;
747856 struct queued_cmd call = {0 };
@@ -751,7 +860,7 @@ static void batch_objects_command(struct batch_options *opt,
751860 if (isspace (* input .buf ))
752861 die (_ ("whitespace before command: '%s'" ), input .buf );
753862
754- for (i = 0 ; i < ARRAY_SIZE (commands ); i ++ ) {
863+ for (size_t i = 0 ; i < ARRAY_SIZE (commands ); i ++ ) {
755864 if (!skip_prefix (input .buf , commands [i ].name , & cmd_end ))
756865 continue ;
757866
0 commit comments