55namespace Microsoft . Build . UniversalPackages ;
66
77using System . Diagnostics ;
8+ #if ! NETFRAMEWORK
9+ using System . Formats . Tar ;
10+ #endif
811using System . IO ;
912using System . IO . Compression ;
1013#if NETFRAMEWORK
@@ -706,7 +709,7 @@ private string GetArtifactToolReleaseInfoUrl(string osName, string arch)
706709 releaseInfo . Value . DownloadUri ,
707710 credentialProviderDir ,
708711 GetArtifactsCredentialProviderRelativePath ( ) ,
709- isZip : RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) ) ;
712+ isZip : releaseInfo . Value . DownloadUri . EndsWith ( ".zip" , StringComparison . OrdinalIgnoreCase ) ) ;
710713 if ( ! downloadResult )
711714 {
712715 return null ;
@@ -754,38 +757,42 @@ private string GetArtifactToolReleaseInfoUrl(string osName, string arch)
754757 Log . LogMessage ( $ "Current Artifacts Credential Provider version: { version } ") ;
755758
756759 string rid ;
757- string fileExtension ;
758760 if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows ) )
759761 {
760762 rid = "win-x64" ;
761- fileExtension = ".zip" ;
762763 }
763764 else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
764765 {
765766 rid = RuntimeInformation . ProcessArchitecture == Architecture . Arm64
766767 ? "linux-arm64"
767768 : "linux-x64" ;
768- fileExtension = ".tar.gz" ;
769769 }
770770 else if ( RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) )
771771 {
772772 rid = RuntimeInformation . ProcessArchitecture == Architecture . Arm64
773773 ? "osx-arm64"
774774 : "osx-x64" ;
775- fileExtension = ".zip" ;
776775 }
777776 else
778777 {
779778 Log . LogError ( $ "Could not determine correct runtime to download the Artifact Credential Provider.") ;
780779 return null ;
781780 }
782781
783- string fileNamePattern = $@ "Microsoft.Net(\d+).{ rid } .NuGet.CredentialProvider{ fileExtension } ";
782+ // We currently only support zip on with .NET Framework.
783+ #if NETFRAMEWORK
784+ const string fileExtention = "zip" ;
785+ #else
786+ const string fileExtention = @"(zip|tar\.gz)" ;
787+ #endif
788+ string fileNamePattern = $@ "Microsoft(\.Net(?<RuntimeVersion>\d+))?\.{ rid } \.NuGet\.CredentialProvider\.{ fileExtention } ";
784789 Log . LogMessage ( MessageImportance . Low , $ "Looking for Artifacts Credential Provider asset with name: { fileNamePattern } ") ;
785- Regex fileNameRegex = new Regex ( fileNamePattern , RegexOptions . IgnoreCase ) ;
790+ Regex fileNameRegex = new Regex ( fileNamePattern , RegexOptions . IgnoreCase | RegexOptions . ExplicitCapture ) ;
791+
792+ List < JsonElement > matchingAssets = new List < JsonElement > ( ) ;
786793
787- int maxNetVersion = 0 ;
788- string ? maxVersionDownloadUrl = null ;
794+ int maxRuntimeVersion = 0 ;
795+ string ? downloadUri = null ;
789796 foreach ( JsonElement asset in root . GetProperty ( "assets" ) . EnumerateArray ( ) )
790797 {
791798 string ? assetName = asset . GetProperty ( "name" ) . GetString ( ) ;
@@ -800,27 +807,38 @@ private string GetArtifactToolReleaseInfoUrl(string osName, string arch)
800807 continue ;
801808 }
802809
803- string netVersionStr = match . Groups [ 1 ] . Value ;
804- if ( ! int . TryParse ( netVersionStr , out int netVersion ) )
810+ Group runtimeVersionGroup = match . Groups [ "RuntimeVersion" ] ;
811+ if ( runtimeVersionGroup . Success )
805812 {
806- continue ;
807- }
813+ if ( ! int . TryParse ( runtimeVersionGroup . Value , out int runtimeVersion ) )
814+ {
815+ continue ;
816+ }
808817
809- if ( netVersion > maxNetVersion )
818+ // Prefer the highest runtime version available.
819+ // Note: Starting in v2 the runtime version is no longer included in the asset name for self-contained flavors of the tool (names sense; it's self-contained).
820+ // Once v2 ships and is stable, this logic can be removed entirely in favor of the pattern without the version.
821+ if ( runtimeVersion > maxRuntimeVersion )
822+ {
823+ maxRuntimeVersion = runtimeVersion ;
824+ downloadUri = asset . GetProperty ( "browser_download_url" ) . GetString ( ) ;
825+ }
826+ }
827+ else
810828 {
811- maxNetVersion = netVersion ;
812- maxVersionDownloadUrl = asset . GetProperty ( "browser_download_url" ) . GetString ( ) ;
829+ downloadUri = asset . GetProperty ( "browser_download_url" ) . GetString ( ) ;
830+
831+ // Newer releases do not have the runtime version in the name, so short circuit once we find one.
832+ break ;
813833 }
814834 }
815835
816- if ( maxVersionDownloadUrl is null )
836+ if ( downloadUri is null )
817837 {
818838 Log . LogError ( $ "Unable to find a download url for the Artifact Credential Provider.") ;
819839 return null ;
820840 }
821841
822- string downloadUri = maxVersionDownloadUrl ;
823-
824842 return ( version , downloadUri ) ;
825843 }
826844
@@ -878,19 +896,18 @@ private bool DownloadAndExtractArchive(string displayName, string downloadUri, s
878896 }
879897 else
880898 {
881- // There is no built-in support for extracting tar.gz files, so fall back to the tar command.
882- // Note: the tar command requires that the destination directory already exist.
899+ #if NETFRAMEWORK
900+ Log . LogError ( $ "Extracting non-zip archives is not supported in this scenario.") ;
901+ return false ;
902+ #else
883903 Directory . CreateDirectory ( archiveExtractPath ) ;
884- int exitCode = ProcessHelper . Execute (
885- "/bin/bash" ,
886- $ "-c \" tar -xzf \\ \" { archiveDownloadPath } \\ \" -C \\ \" { archiveExtractPath } \\ \" \" ",
887- processStdOut : message => Log . LogMessage ( MessageImportance . Low , message ) ,
888- processStdErr : message => Log . LogError ( message ) ) ;
889- if ( exitCode != 0 )
904+
905+ using ( var archiveStream = File . OpenRead ( archiveDownloadPath ) )
906+ using ( var archiveGzipStream = new GZipStream ( archiveStream , CompressionMode . Decompress ) )
890907 {
891- Log . LogError ( $ "Extracting Artifacts Credential Provider failed with exit code: { exitCode } ") ;
892- return false ;
908+ TarFile . ExtractToDirectory ( archiveGzipStream , archiveExtractPath , overwriteFiles : false ) ;
893909 }
910+ #endif
894911 }
895912
896913 Log . LogMessage ( MessageImportance . Low , "Extracted Artifacts Credential Provider" ) ;
0 commit comments