5
5
using System . Linq ;
6
6
using System . Security . Cryptography ;
7
7
using System . Text ;
8
+ using System . Text . RegularExpressions ;
8
9
using System . Threading . Tasks ;
9
10
using Semmle . Util ;
10
11
using Semmle . Util . Logging ;
@@ -14,7 +15,7 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
14
15
/// <summary>
15
16
/// Main implementation of the build analysis.
16
17
/// </summary>
17
- public sealed class DependencyManager : IDisposable
18
+ public sealed partial class DependencyManager : IDisposable
18
19
{
19
20
private readonly AssemblyCache assemblyCache ;
20
21
private readonly ILogger logger ;
@@ -783,13 +784,53 @@ private void RestoreProjects(IEnumerable<string> projects, out IEnumerable<strin
783
784
CompilationInfos . Add ( ( "Successfully restored project files" , successCount . ToString ( ) ) ) ;
784
785
}
785
786
786
- private void DownloadMissingPackages ( List < FileInfo > allFiles , ISet < string > dllPaths )
787
+ [ GeneratedRegex ( @"^(.+)\.(\d+\.\d+\.\d+(-(.+))?)$" , RegexOptions . IgnoreCase | RegexOptions . Compiled | RegexOptions . Singleline ) ]
788
+ private static partial Regex LegacyNugetPackage ( ) ;
789
+
790
+
791
+ private static IEnumerable < string > GetRestoredPackageDirectoryNames ( DirectoryInfo root )
787
792
{
788
- var alreadyDownloadedPackages = Directory . GetDirectories ( packageDirectory . DirInfo . FullName )
793
+ return Directory . GetDirectories ( root . FullName )
789
794
. Select ( d => Path . GetFileName ( d ) . ToLowerInvariant ( ) ) ;
790
- var notYetDownloadedPackages = fileContent . AllPackages
791
- . Except ( alreadyDownloadedPackages )
792
- . ToList ( ) ;
795
+ }
796
+
797
+ private IEnumerable < string > GetRestoredLegacyPackageNames ( )
798
+ {
799
+ var oldPackageDirectories = GetRestoredPackageDirectoryNames ( legacyPackageDirectory . DirInfo ) ;
800
+ foreach ( var oldPackageDirectory in oldPackageDirectories )
801
+ {
802
+ // nuget install restores packages to 'packagename.version' folders (dotnet restore to 'packagename/version' folders)
803
+ // typical folder names look like:
804
+ // newtonsoft.json.13.0.3
805
+ // there are more complex ones too, such as:
806
+ // runtime.tizen.4.0.0-armel.Microsoft.NETCore.DotNetHostResolver.2.0.0-preview2-25407-01
807
+
808
+ var match = LegacyNugetPackage ( ) . Match ( oldPackageDirectory ) ;
809
+ if ( ! match . Success )
810
+ {
811
+ logger . LogWarning ( $ "Package directory '{ oldPackageDirectory } ' doesn't match the expected pattern.") ;
812
+ continue ;
813
+ }
814
+
815
+ yield return match . Groups [ 1 ] . Value . ToLowerInvariant ( ) ;
816
+ }
817
+ }
818
+
819
+ private void DownloadMissingPackages ( List < FileInfo > allFiles , ISet < string > dllPaths )
820
+ {
821
+ var alreadyDownloadedPackages = GetRestoredPackageDirectoryNames ( packageDirectory . DirInfo ) ;
822
+ var alreadyDownloadedLegacyPackages = GetRestoredLegacyPackageNames ( ) ;
823
+
824
+ var notYetDownloadedPackages = new HashSet < string > ( fileContent . AllPackages ) ;
825
+ foreach ( var alreadyDownloadedPackage in alreadyDownloadedPackages )
826
+ {
827
+ notYetDownloadedPackages . Remove ( alreadyDownloadedPackage ) ;
828
+ }
829
+ foreach ( var alreadyDownloadedLegacyPackage in alreadyDownloadedLegacyPackages )
830
+ {
831
+ notYetDownloadedPackages . Remove ( alreadyDownloadedLegacyPackage ) ;
832
+ }
833
+
793
834
if ( notYetDownloadedPackages . Count == 0 )
794
835
{
795
836
return ;
0 commit comments