@@ -314,10 +314,37 @@ static int allow_unsanitized(char ch)
314314 return ch > 32 && ch < 127 ;
315315}
316316
317- static void promisor_info_vecs (struct repository * repo ,
318- struct strvec * names ,
319- struct strvec * urls )
317+ /*
318+ * Linked list for promisor remotes involved in the "promisor-remote"
319+ * protocol capability.
320+ *
321+ * Except for "next" and "name", each <member> in this struct and its
322+ * <value> should correspond to a "remote.<name>.<member>" config
323+ * variable set to <value> where "<name>" is a promisor remote name.
324+ */
325+ struct promisor_info {
326+ struct promisor_info * next ;
327+ const char * name ;
328+ const char * url ;
329+ };
330+
331+ static void promisor_info_list_free (struct promisor_info * p )
332+ {
333+ struct promisor_info * next ;
334+
335+ for (; p ; p = next ) {
336+ next = p -> next ;
337+ free ((char * )p -> name );
338+ free ((char * )p -> url );
339+ free (p );
340+ }
341+ }
342+
343+ /* Prepare a 'struct promisor_info' linked list with config information. */
344+ static struct promisor_info * promisor_config_info_list (struct repository * repo )
320345{
346+ struct promisor_info * infos = NULL ;
347+ struct promisor_info * * last_info = & infos ;
321348 struct promisor_remote * r ;
322349
323350 promisor_remote_init (repo );
@@ -328,57 +355,65 @@ static void promisor_info_vecs(struct repository *repo,
328355
329356 /* Only add remotes with a non empty URL */
330357 if (!git_config_get_string_tmp (url_key , & url ) && * url ) {
331- strvec_push (names , r -> name );
332- strvec_push (urls , url );
358+ struct promisor_info * new_info = xcalloc (1 , sizeof (* new_info ));
359+
360+ new_info -> name = xstrdup (r -> name );
361+ new_info -> url = xstrdup (url );
362+
363+ * last_info = new_info ;
364+ last_info = & new_info -> next ;
333365 }
334366
335367 free (url_key );
336368 }
369+
370+ return infos ;
337371}
338372
339373char * promisor_remote_info (struct repository * repo )
340374{
341375 struct strbuf sb = STRBUF_INIT ;
342376 int advertise_promisors = 0 ;
343- struct strvec names = STRVEC_INIT ;
344- struct strvec urls = STRVEC_INIT ;
377+ struct promisor_info * config_info ;
378+ struct promisor_info * p ;
345379
346380 git_config_get_bool ("promisor.advertise" , & advertise_promisors );
347381
348382 if (!advertise_promisors )
349383 return NULL ;
350384
351- promisor_info_vecs ( repo , & names , & urls );
385+ config_info = promisor_config_info_list ( repo );
352386
353- if (!names . nr )
387+ if (!config_info )
354388 return NULL ;
355389
356- for (size_t i = 0 ; i < names . nr ; i ++ ) {
357- if (i )
390+ for (p = config_info ; p ; p = p -> next ) {
391+ if (p != config_info )
358392 strbuf_addch (& sb , ';' );
393+
359394 strbuf_addstr (& sb , "name=" );
360- strbuf_addstr_urlencode (& sb , names . v [ i ] , allow_unsanitized );
395+ strbuf_addstr_urlencode (& sb , p -> name , allow_unsanitized );
361396 strbuf_addstr (& sb , ",url=" );
362- strbuf_addstr_urlencode (& sb , urls . v [ i ] , allow_unsanitized );
397+ strbuf_addstr_urlencode (& sb , p -> url , allow_unsanitized );
363398 }
364399
365- strvec_clear (& names );
366- strvec_clear (& urls );
400+ promisor_info_list_free (config_info );
367401
368402 return strbuf_detach (& sb , NULL );
369403}
370404
371405/*
372- * Find first index of 'nicks ' where there is 'nick'. 'nick' is
373- * compared case sensitively to the strings in 'nicks '. If not found
374- * 'nicks->nr' is returned.
406+ * Find first element of 'p ' where the 'name' member is 'nick'. 'nick'
407+ * is compared case sensitively to the strings in 'p '. If not found
408+ * NULL is returned.
375409 */
376- static size_t remote_nick_find (struct strvec * nicks , const char * nick )
410+ static struct promisor_info * remote_nick_find (struct promisor_info * p , const char * nick )
377411{
378- for (size_t i = 0 ; i < nicks -> nr ; i ++ )
379- if (!strcmp (nicks -> v [i ], nick ))
380- return i ;
381- return nicks -> nr ;
412+ for (; p ; p = p -> next ) {
413+ if (!strcmp (p -> name , nick ))
414+ return p ;
415+ }
416+ return NULL ;
382417}
383418
384419enum accept_promisor {
@@ -390,16 +425,16 @@ enum accept_promisor {
390425
391426static int should_accept_remote (enum accept_promisor accept ,
392427 const char * remote_name , const char * remote_url ,
393- struct strvec * names , struct strvec * urls )
428+ struct promisor_info * config_info )
394429{
395- size_t i ;
430+ struct promisor_info * p ;
396431
397432 if (accept == ACCEPT_ALL )
398433 return 1 ;
399434
400- i = remote_nick_find (names , remote_name );
435+ p = remote_nick_find (config_info , remote_name );
401436
402- if (i >= names -> nr )
437+ if (! p )
403438 /* We don't know about that remote */
404439 return 0 ;
405440
@@ -414,11 +449,15 @@ static int should_accept_remote(enum accept_promisor accept,
414449 return 0 ;
415450 }
416451
417- if (!strcmp (urls -> v [i ], remote_url ))
452+ if (!p -> url )
453+ BUG ("Bad config_info (invalid URL) for remote '%s'.\n" ,
454+ remote_name );
455+
456+ if (!strcmp (p -> url , remote_url ))
418457 return 1 ;
419458
420459 warning (_ ("known remote named '%s' but with URL '%s' instead of '%s'" ),
421- remote_name , urls -> v [ i ] , remote_url );
460+ remote_name , p -> url , remote_url );
422461
423462 return 0 ;
424463}
@@ -430,8 +469,7 @@ static void filter_promisor_remote(struct repository *repo,
430469 struct strbuf * * remotes ;
431470 const char * accept_str ;
432471 enum accept_promisor accept = ACCEPT_NONE ;
433- struct strvec names = STRVEC_INIT ;
434- struct strvec urls = STRVEC_INIT ;
472+ struct promisor_info * config_info = NULL ;
435473
436474 if (!git_config_get_string_tmp ("promisor.acceptfromserver" , & accept_str )) {
437475 if (!* accept_str || !strcasecmp ("None" , accept_str ))
@@ -451,7 +489,7 @@ static void filter_promisor_remote(struct repository *repo,
451489 return ;
452490
453491 if (accept != ACCEPT_ALL )
454- promisor_info_vecs ( repo , & names , & urls );
492+ config_info = promisor_config_info_list ( repo );
455493
456494 /* Parse remote info received */
457495
@@ -482,16 +520,15 @@ static void filter_promisor_remote(struct repository *repo,
482520 if (remote_url )
483521 decoded_url = url_percent_decode (remote_url );
484522
485- if (decoded_name && should_accept_remote (accept , decoded_name , decoded_url , & names , & urls ))
523+ if (decoded_name && should_accept_remote (accept , decoded_name , decoded_url , config_info ))
486524 strvec_push (accepted , decoded_name );
487525
488526 strbuf_list_free (elems );
489527 free (decoded_name );
490528 free (decoded_url );
491529 }
492530
493- strvec_clear (& names );
494- strvec_clear (& urls );
531+ promisor_info_list_free (config_info );
495532 strbuf_list_free (remotes );
496533}
497534
0 commit comments