@@ -492,10 +492,23 @@ def is_usable_module(self, name):
492492 def cfg_version (self , default ):
493493 return PPG .config .get_value ("%s-version" % self .m_name ) or default
494494
495+ def cfg_http_headers (self ):
496+ if config_http_headers := PPG .config .get_value ("%s-http-headers" % self .m_name ):
497+ expanded_http_headers = {}
498+ for header_dict in config_http_headers :
499+ for key , value in header_dict .items ():
500+ expanded_http_headers [os .path .expandvars (key )] = os .path .expandvars (value )
501+
502+ return expanded_http_headers
503+
495504 def cfg_url (self , version ):
496505 if config_url := PPG .config .get_value ("%s-url" % self .m_name ):
497506 url_template = Template (config_url )
498- return url_template .substitute (version = version )
507+ url_subbed = url_template .substitute (version = version )
508+ return os .path .expandvars (url_subbed )
509+
510+ def cfg_src_suffix (self ):
511+ return PPG .config .get_value ("%s-src-suffix" % self .m_name )
499512
500513 def cfg_configure (self , deps_lib_dir , deps_lib64_dir ):
501514 if configure := PPG .config .get_value ("%s-configure" % self .m_name ):
@@ -510,6 +523,16 @@ def url(self):
510523 """Url of source tarball, if any"""
511524 return ""
512525
526+ @property
527+ def headers (self ):
528+ """Headers for connecting to source url, if any"""
529+ return self .cfg_http_headers ()
530+
531+ @property
532+ def src_suffix (self ):
533+ """Suffix of src archive for when URL doesn't end in the file extension"""
534+ return self .cfg_src_suffix ()
535+
513536 @property
514537 def version (self ):
515538 """Version to use"""
@@ -632,8 +655,16 @@ def compile(self):
632655 self ._finalize ()
633656 return
634657
658+ # Some URL's may not end in file extension, such as with redirects.
659+ # Github releases asset endpoint is this way .../releases/assets/48151
660+
635661 # Split on '#' for urls that include a checksum, such as #sha256=... fragment
636662 basename = runez .basename (self .url , extension_marker = "#" )
663+ if not basename .endswith ((".zip" , ".tar.gz" )):
664+ suffix = self .src_suffix or ".tar.gz"
665+ suffix = ".%s" % (suffix .strip ("." )) # Ensure it starts with a dot (in case config forgot leading dot)
666+ basename = f"{ self .m_name } -{ self .version } { suffix } "
667+
637668 path = self .setup .folders .sources / basename
638669 if not path .exists ():
639670 proxies = {}
@@ -643,7 +674,8 @@ def compile(self):
643674 https_proxy = os .environ .get ("HTTPS_PROXY" ) or os .environ .get ("https_proxy" )
644675 if https_proxy :
645676 proxies ["https" ] = https_proxy
646- RestClient ().download (self .url , path , proxies = proxies )
677+
678+ RestClient ().download (self .url , path , proxies = proxies , headers = self .headers )
647679
648680 runez .decompress (path , self .m_src_build , simplify = True )
649681
0 commit comments