@@ -37,6 +37,10 @@ int credential_match(const struct credential *want,
3737#undef CHECK
3838}
3939
40+
41+ static int credential_from_potentially_partial_url (struct credential * c ,
42+ const char * url );
43+
4044static int credential_config_callback (const char * var , const char * value ,
4145 void * data )
4246{
@@ -377,8 +381,31 @@ static int check_url_component(const char *url, int quiet,
377381 return -1 ;
378382}
379383
380- int credential_from_url_gently (struct credential * c , const char * url ,
381- int quiet )
384+ /*
385+ * Potentially-partial URLs can, but do not have to, contain
386+ *
387+ * - a protocol (or scheme) of the form "<protocol>://"
388+ *
389+ * - a host name (the part after the protocol and before the first slash after
390+ * that, if any)
391+ *
392+ * - a user name and potentially a password (as "<user>[:<password>]@" part of
393+ * the host name)
394+ *
395+ * - a path (the part after the host name, if any, starting with the slash)
396+ *
397+ * Missing parts will be left unset in `struct credential`. Thus, `https://`
398+ * will have only the `protocol` set, `example.com` only the host name, and
399+ * `/git` only the path.
400+ *
401+ * Note that an empty host name in an otherwise fully-qualified URL (e.g.
402+ * `cert:///path/to/cert.pem`) will be treated as unset if we expect the URL to
403+ * be potentially partial, and only then (otherwise, the empty string is used).
404+ *
405+ * The credential_from_url() function does not allow partial URLs.
406+ */
407+ static int credential_from_url_1 (struct credential * c , const char * url ,
408+ int allow_partial_url , int quiet )
382409{
383410 const char * at , * colon , * cp , * slash , * host , * proto_end ;
384411
@@ -391,12 +418,12 @@ int credential_from_url_gently(struct credential *c, const char *url,
391418 * (3) proto://<user>:<pass>@<host>/...
392419 */
393420 proto_end = strstr (url , "://" );
394- if (!proto_end || proto_end == url ) {
421+ if (!allow_partial_url && (! proto_end || proto_end == url ) ) {
395422 if (!quiet )
396423 warning (_ ("url has no scheme: %s" ), url );
397424 return -1 ;
398425 }
399- cp = proto_end + 3 ;
426+ cp = proto_end ? proto_end + 3 : url ;
400427 at = strchr (cp , '@' );
401428 colon = strchr (cp , ':' );
402429
@@ -427,8 +454,10 @@ int credential_from_url_gently(struct credential *c, const char *url,
427454 host = at + 1 ;
428455 }
429456
430- c -> protocol = xmemdupz (url , proto_end - url );
431- c -> host = url_decode_mem (host , slash - host );
457+ if (proto_end && proto_end - url > 0 )
458+ c -> protocol = xmemdupz (url , proto_end - url );
459+ if (!allow_partial_url || slash - host > 0 )
460+ c -> host = url_decode_mem (host , slash - host );
432461 /* Trim leading and trailing slashes from path */
433462 while (* slash == '/' )
434463 slash ++ ;
@@ -450,6 +479,17 @@ int credential_from_url_gently(struct credential *c, const char *url,
450479 return 0 ;
451480}
452481
482+ static int credential_from_potentially_partial_url (struct credential * c ,
483+ const char * url )
484+ {
485+ return credential_from_url_1 (c , url , 1 , 0 );
486+ }
487+
488+ int credential_from_url_gently (struct credential * c , const char * url , int quiet )
489+ {
490+ return credential_from_url_1 (c , url , 0 , quiet );
491+ }
492+
453493void credential_from_url (struct credential * c , const char * url )
454494{
455495 if (credential_from_url_gently (c , url , 0 ) < 0 )
0 commit comments