1212#include "sha1-array.h"
1313#include "transport.h"
1414#include "strbuf.h"
15+ #include "version.h"
1516#include "protocol.h"
1617
17- static char * server_capabilities ;
18+ static char * server_capabilities_v1 ;
19+ static struct argv_array server_capabilities_v2 = ARGV_ARRAY_INIT ;
1820static const char * parse_feature_value (const char * , const char * , int * );
1921
2022static int check_ref (const char * name , unsigned int flags )
@@ -62,6 +64,33 @@ static void die_initial_contact(int unexpected)
6264 "and the repository exists." ));
6365}
6466
67+ /* Checks if the server supports the capability 'c' */
68+ int server_supports_v2 (const char * c , int die_on_error )
69+ {
70+ int i ;
71+
72+ for (i = 0 ; i < server_capabilities_v2 .argc ; i ++ ) {
73+ const char * out ;
74+ if (skip_prefix (server_capabilities_v2 .argv [i ], c , & out ) &&
75+ (!* out || * out == '=' ))
76+ return 1 ;
77+ }
78+
79+ if (die_on_error )
80+ die ("server doesn't support '%s'" , c );
81+
82+ return 0 ;
83+ }
84+
85+ static void process_capabilities_v2 (struct packet_reader * reader )
86+ {
87+ while (packet_reader_read (reader ) == PACKET_READ_NORMAL )
88+ argv_array_push (& server_capabilities_v2 , reader -> line );
89+
90+ if (reader -> status != PACKET_READ_FLUSH )
91+ die ("expected flush after capabilities" );
92+ }
93+
6594enum protocol_version discover_version (struct packet_reader * reader )
6695{
6796 enum protocol_version version = protocol_unknown_version ;
@@ -84,7 +113,7 @@ enum protocol_version discover_version(struct packet_reader *reader)
84113
85114 switch (version ) {
86115 case protocol_v2 :
87- die ( "support for protocol v2 not implemented yet" );
116+ process_capabilities_v2 ( reader );
88117 break ;
89118 case protocol_v1 :
90119 /* Read the peeked version line */
@@ -128,7 +157,7 @@ static void parse_one_symref_info(struct string_list *symref, const char *val, i
128157static void annotate_refs_with_symref_info (struct ref * ref )
129158{
130159 struct string_list symref = STRING_LIST_INIT_DUP ;
131- const char * feature_list = server_capabilities ;
160+ const char * feature_list = server_capabilities_v1 ;
132161
133162 while (feature_list ) {
134163 int len ;
@@ -157,7 +186,7 @@ static void process_capabilities(const char *line, int *len)
157186 int nul_location = strlen (line );
158187 if (nul_location == * len )
159188 return ;
160- server_capabilities = xstrdup (line + nul_location + 1 );
189+ server_capabilities_v1 = xstrdup (line + nul_location + 1 );
161190 * len = nul_location ;
162191}
163192
@@ -292,6 +321,105 @@ struct ref **get_remote_heads(struct packet_reader *reader,
292321 return list ;
293322}
294323
324+ /* Returns 1 when a valid ref has been added to `list`, 0 otherwise */
325+ static int process_ref_v2 (const char * line , struct ref * * * list )
326+ {
327+ int ret = 1 ;
328+ int i = 0 ;
329+ struct object_id old_oid ;
330+ struct ref * ref ;
331+ struct string_list line_sections = STRING_LIST_INIT_DUP ;
332+ const char * end ;
333+
334+ /*
335+ * Ref lines have a number of fields which are space deliminated. The
336+ * first field is the OID of the ref. The second field is the ref
337+ * name. Subsequent fields (symref-target and peeled) are optional and
338+ * don't have a particular order.
339+ */
340+ if (string_list_split (& line_sections , line , ' ' , -1 ) < 2 ) {
341+ ret = 0 ;
342+ goto out ;
343+ }
344+
345+ if (parse_oid_hex (line_sections .items [i ++ ].string , & old_oid , & end ) ||
346+ * end ) {
347+ ret = 0 ;
348+ goto out ;
349+ }
350+
351+ ref = alloc_ref (line_sections .items [i ++ ].string );
352+
353+ oidcpy (& ref -> old_oid , & old_oid );
354+ * * list = ref ;
355+ * list = & ref -> next ;
356+
357+ for (; i < line_sections .nr ; i ++ ) {
358+ const char * arg = line_sections .items [i ].string ;
359+ if (skip_prefix (arg , "symref-target:" , & arg ))
360+ ref -> symref = xstrdup (arg );
361+
362+ if (skip_prefix (arg , "peeled:" , & arg )) {
363+ struct object_id peeled_oid ;
364+ char * peeled_name ;
365+ struct ref * peeled ;
366+ if (parse_oid_hex (arg , & peeled_oid , & end ) || * end ) {
367+ ret = 0 ;
368+ goto out ;
369+ }
370+
371+ peeled_name = xstrfmt ("%s^{}" , ref -> name );
372+ peeled = alloc_ref (peeled_name );
373+
374+ oidcpy (& peeled -> old_oid , & peeled_oid );
375+ * * list = peeled ;
376+ * list = & peeled -> next ;
377+
378+ free (peeled_name );
379+ }
380+ }
381+
382+ out :
383+ string_list_clear (& line_sections , 0 );
384+ return ret ;
385+ }
386+
387+ struct ref * * get_remote_refs (int fd_out , struct packet_reader * reader ,
388+ struct ref * * list , int for_push ,
389+ const struct argv_array * ref_prefixes )
390+ {
391+ int i ;
392+ * list = NULL ;
393+
394+ if (server_supports_v2 ("ls-refs" , 1 ))
395+ packet_write_fmt (fd_out , "command=ls-refs\n" );
396+
397+ if (server_supports_v2 ("agent" , 0 ))
398+ packet_write_fmt (fd_out , "agent=%s" , git_user_agent_sanitized ());
399+
400+ packet_delim (fd_out );
401+ /* When pushing we don't want to request the peeled tags */
402+ if (!for_push )
403+ packet_write_fmt (fd_out , "peel\n" );
404+ packet_write_fmt (fd_out , "symrefs\n" );
405+ for (i = 0 ; ref_prefixes && i < ref_prefixes -> argc ; i ++ ) {
406+ packet_write_fmt (fd_out , "ref-prefix %s\n" ,
407+ ref_prefixes -> argv [i ]);
408+ }
409+ packet_flush (fd_out );
410+
411+ /* Process response from server */
412+ while (packet_reader_read (reader ) == PACKET_READ_NORMAL ) {
413+ if (!process_ref_v2 (reader -> line , & list ))
414+ die ("invalid ls-refs response: %s" , reader -> line );
415+ }
416+
417+ if (reader -> status != PACKET_READ_FLUSH )
418+ die ("expected flush after ref listing" );
419+
420+ return list ;
421+ }
422+
295423static const char * parse_feature_value (const char * feature_list , const char * feature , int * lenp )
296424{
297425 int len ;
@@ -336,7 +464,7 @@ int parse_feature_request(const char *feature_list, const char *feature)
336464
337465const char * server_feature_value (const char * feature , int * len )
338466{
339- return parse_feature_value (server_capabilities , feature , len );
467+ return parse_feature_value (server_capabilities_v1 , feature , len );
340468}
341469
342470int server_supports (const char * feature )
0 commit comments