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 ;
@@ -628,6 +642,61 @@ static void batch_one_object(const char *obj_name,
628642 object_context_release (& ctx );
629643}
630644
645+ static int get_remote_info (struct batch_options * opt , int argc , const char * * argv )
646+ {
647+ int retval = 0 ;
648+ struct remote * remote = NULL ;
649+ struct object_id oid ;
650+ struct string_list object_info_options = STRING_LIST_INIT_NODUP ;
651+ static struct transport * gtransport ;
652+
653+ /*
654+ * Change the format to "%(objectname) %(objectsize)" when
655+ * remote-object-info command is used. Once we start supporting objecttype
656+ * the default format should change to DEFAULT_FORMAT.
657+ */
658+ if (!opt -> format )
659+ opt -> format = "%(objectname) %(objectsize)" ;
660+
661+ remote = remote_get (argv [0 ]);
662+ if (!remote )
663+ die (_ ("must supply valid remote when using remote-object-info" ));
664+
665+ oid_array_clear (& object_info_oids );
666+ for (size_t i = 1 ; i < argc ; i ++ ) {
667+ if (get_oid_hex (argv [i ], & oid ))
668+ die (_ ("Not a valid object name %s" ), argv [i ]);
669+ oid_array_append (& object_info_oids , & oid );
670+ }
671+ if (!object_info_oids .nr )
672+ die (_ ("remote-object-info requires objects" ));
673+
674+ gtransport = transport_get (remote , NULL );
675+ if (gtransport -> smart_options ) {
676+ CALLOC_ARRAY (remote_object_info , object_info_oids .nr );
677+ gtransport -> smart_options -> object_info = 1 ;
678+ gtransport -> smart_options -> object_info_oids = & object_info_oids ;
679+
680+ /* 'objectsize' is the only option currently supported */
681+ if (!strstr (opt -> format , "%(objectsize)" ))
682+ die (_ ("%s is currently not supported with remote-object-info" ), opt -> format );
683+
684+ string_list_append (& object_info_options , "size" );
685+
686+ if (object_info_options .nr > 0 ) {
687+ gtransport -> smart_options -> object_info_options = & object_info_options ;
688+ gtransport -> smart_options -> object_info_data = remote_object_info ;
689+ retval = transport_fetch_refs (gtransport , NULL );
690+ }
691+ } else {
692+ retval = -1 ;
693+ }
694+
695+ string_list_clear (& object_info_options , 0 );
696+ transport_disconnect (gtransport );
697+ return retval ;
698+ }
699+
631700struct object_cb_data {
632701 struct batch_options * opt ;
633702 struct expand_data * expand ;
@@ -695,28 +764,68 @@ static void parse_cmd_info(struct batch_options *opt,
695764 batch_one_object (line , output , opt , data );
696765}
697766
767+ static void parse_cmd_remote_object_info (struct batch_options * opt ,
768+ const char * line , struct strbuf * output ,
769+ struct expand_data * data )
770+ {
771+ int count ;
772+ const char * * argv ;
773+ char * line_to_split ;
774+
775+ if (strlen (line ) >= MAX_REMOTE_OBJ_INFO_LINE )
776+ die (_ ("remote-object-info command input overflow "
777+ "(no more than %d objects are allowed)" ),
778+ MAX_ALLOWED_OBJ_LIMIT );
779+
780+ line_to_split = xstrdup (line );
781+ count = split_cmdline (line_to_split , & argv );
782+ if (count < 0 )
783+ die (_ ("split remote-object-info command" ));
784+
785+ if (get_remote_info (opt , count , argv ))
786+ goto cleanup ;
787+
788+ data -> skip_object_info = 1 ;
789+ for (size_t i = 0 ; i < object_info_oids .nr ; i ++ ) {
790+ data -> oid = object_info_oids .oid [i ];
791+ if (remote_object_info [i ].sizep ) {
792+ /*
793+ * When reaching here, it means remote-object-info can retrieve
794+ * information from server without downloading them.
795+ */
796+ data -> size = * remote_object_info [i ].sizep ;
797+ opt -> batch_mode = BATCH_MODE_INFO ;
798+ batch_object_write (argv [i + 1 ], output , opt , data , NULL , 0 );
799+ }
800+ }
801+ data -> skip_object_info = 0 ;
802+
803+ cleanup :
804+ for (size_t i = 0 ; i < object_info_oids .nr ; i ++ )
805+ free_object_info_contents (& remote_object_info [i ]);
806+ free (line_to_split );
807+ free (argv );
808+ free (remote_object_info );
809+ }
810+
698811static void dispatch_calls (struct batch_options * opt ,
699812 struct strbuf * output ,
700813 struct expand_data * data ,
701814 struct queued_cmd * cmd ,
702815 int nr )
703816{
704- int i ;
705-
706817 if (!opt -> buffer_output )
707818 die (_ ("flush is only for --buffer mode" ));
708819
709- for (i = 0 ; i < nr ; i ++ )
820+ for (size_t i = 0 ; i < nr ; i ++ )
710821 cmd [i ].fn (opt , cmd [i ].line , output , data );
711822
712823 fflush (stdout );
713824}
714825
715826static void free_cmds (struct queued_cmd * cmd , size_t * nr )
716827{
717- size_t i ;
718-
719- for (i = 0 ; i < * nr ; i ++ )
828+ for (size_t i = 0 ; i < * nr ; i ++ )
720829 FREE_AND_NULL (cmd [i ].line );
721830
722831 * nr = 0 ;
@@ -730,6 +839,7 @@ static const struct parse_cmd {
730839} commands [] = {
731840 { "contents" , parse_cmd_contents , 1 },
732841 { "info" , parse_cmd_info , 1 },
842+ { "remote-object-info" , parse_cmd_remote_object_info , 1 },
733843 { "flush" , NULL , 0 },
734844};
735845
@@ -742,7 +852,6 @@ static void batch_objects_command(struct batch_options *opt,
742852 size_t alloc = 0 , nr = 0 ;
743853
744854 while (strbuf_getdelim_strip_crlf (& input , stdin , opt -> input_delim ) != EOF ) {
745- int i ;
746855 const struct parse_cmd * cmd = NULL ;
747856 const char * p = NULL , * cmd_end ;
748857 struct queued_cmd call = {0 };
@@ -752,7 +861,7 @@ static void batch_objects_command(struct batch_options *opt,
752861 if (isspace (* input .buf ))
753862 die (_ ("whitespace before command: '%s'" ), input .buf );
754863
755- for (i = 0 ; i < ARRAY_SIZE (commands ); i ++ ) {
864+ for (size_t i = 0 ; i < ARRAY_SIZE (commands ); i ++ ) {
756865 if (!skip_prefix (input .buf , commands [i ].name , & cmd_end ))
757866 continue ;
758867
0 commit comments