11using System ;
2- using System . Collections . Generic ;
32using System . Diagnostics ;
43using System . IO ;
54using System . Linq ;
@@ -14,70 +13,91 @@ namespace Semmle.Extraction.CSharp.DependencyFetching
1413 /// </summary>
1514 internal class NugetPackages
1615 {
16+ private readonly string nugetExe ;
17+ private readonly ProgressMonitor progressMonitor ;
18+
19+ /// <summary>
20+ /// The list of package files.
21+ /// </summary>
22+ private readonly FileInfo [ ] packageFiles ;
23+
24+ /// <summary>
25+ /// The computed packages directory.
26+ /// This will be in the Temp location
27+ /// so as to not trample the source tree.
28+ /// </summary>
29+ private readonly TemporaryDirectory packageDirectory ;
30+
1731 /// <summary>
1832 /// Create the package manager for a specified source tree.
1933 /// </summary>
2034 public NugetPackages ( string sourceDir , TemporaryDirectory packageDirectory , ProgressMonitor progressMonitor )
2135 {
22- SourceDirectory = sourceDir ;
23- PackageDirectory = packageDirectory ;
36+ this . packageDirectory = packageDirectory ;
2437 this . progressMonitor = progressMonitor ;
2538
26- // Expect nuget.exe to be in a `nuget` directory under the directory containing this exe.
27- var currentAssembly = System . Reflection . Assembly . GetExecutingAssembly ( ) . Location ;
28- var directory = Path . GetDirectoryName ( currentAssembly )
29- ?? throw new FileNotFoundException ( $ "Directory path '{ currentAssembly } ' of current assembly is null") ;
30- nugetExe = Path . Combine ( directory , "nuget" , "nuget.exe" ) ;
31-
32- if ( ! File . Exists ( nugetExe ) )
33- throw new FileNotFoundException ( string . Format ( "NuGet could not be found at {0}" , nugetExe ) ) ;
34-
35- packages = new DirectoryInfo ( SourceDirectory )
39+ nugetExe = ResolveNugetExe ( sourceDir ) ;
40+ packageFiles = new DirectoryInfo ( sourceDir )
3641 . EnumerateFiles ( "packages.config" , SearchOption . AllDirectories )
3742 . ToArray ( ) ;
3843 }
3944
40- // List of package files to download.
41- private readonly FileInfo [ ] packages ;
42-
43- /// <summary>
44- /// The list of package files.
45- /// </summary>
46- public IEnumerable < FileInfo > PackageFiles => packages ;
47-
4845 /// <summary>
49- /// Download the packages to the temp folder.
46+ /// Tries to find the location of `nuget.exe` in the nuget directory under the directory
47+ /// containing the executing assembly. If it can't be found, it is downloaded to the
48+ /// `.nuget` directory under the source directory.
5049 /// </summary>
51- /// <param name="pm ">The progress monitor used for reporting errors etc .</param>
52- public void InstallPackages ( )
50+ /// <param name="sourceDir ">The source directory .</param>
51+ private string ResolveNugetExe ( string sourceDir )
5352 {
54- foreach ( var package in packages )
53+ var currentAssembly = System . Reflection . Assembly . GetExecutingAssembly ( ) . Location ;
54+ var directory = Path . GetDirectoryName ( currentAssembly )
55+ ?? throw new FileNotFoundException ( $ "Directory path '{ currentAssembly } ' of current assembly is null") ;
56+
57+ var nuget = Path . Combine ( directory , "nuget" , "nuget.exe" ) ;
58+ if ( File . Exists ( nuget ) )
5559 {
56- RestoreNugetPackage ( package . FullName ) ;
60+ progressMonitor . FoundNuGet ( nuget ) ;
61+ return nuget ;
62+ }
63+ else
64+ {
65+ progressMonitor . LogInfo ( $ "Nuget.exe could not be found at { nuget } ") ;
66+ return DownloadNugetExe ( sourceDir ) ;
5767 }
5868 }
5969
60- /// <summary>
61- /// The source directory used.
62- /// </summary>
63- public string SourceDirectory
70+ private string DownloadNugetExe ( string sourceDir )
6471 {
65- get ;
66- private set ;
67- }
72+ var directory = Path . Combine ( sourceDir , ".nuget" ) ;
73+ var nuget = Path . Combine ( directory , "nuget.exe" ) ;
6874
69- /// <summary>
70- /// The computed packages directory.
71- /// This will be in the Temp location
72- /// so as to not trample the source tree.
73- /// </summary>
74- public TemporaryDirectory PackageDirectory { get ; }
75+ // Nuget.exe already exists in the .nuget directory.
76+ if ( File . Exists ( nuget ) )
77+ {
78+ progressMonitor . FoundNuGet ( nuget ) ;
79+ return nuget ;
80+ }
81+
82+ Directory . CreateDirectory ( directory ) ;
83+ progressMonitor . LogInfo ( "Attempting to download nuget.exe" ) ;
84+ try
85+ {
86+ FileUtils . DownloadFile ( FileUtils . NugetExeUrl , nuget ) ;
87+ progressMonitor . LogInfo ( $ "Downloaded nuget.exe to { nuget } ") ;
88+ return nuget ;
89+ }
90+ catch
91+ {
92+ // Download failed.
93+ throw new FileNotFoundException ( "Download of nuget.exe failed." ) ;
94+ }
95+ }
7596
7697 /// <summary>
7798 /// Restore all files in a specified package.
7899 /// </summary>
79100 /// <param name="package">The package file.</param>
80- /// <param name="pm">Where to log progress/errors.</param>
81101 private void RestoreNugetPackage ( string package )
82102 {
83103 progressMonitor . NugetInstall ( package ) ;
@@ -92,12 +112,12 @@ private void RestoreNugetPackage(string package)
92112 if ( Util . Win32 . IsWindows ( ) )
93113 {
94114 exe = nugetExe ;
95- args = string . Format ( "install -OutputDirectory {0} {1}" , PackageDirectory , package ) ;
115+ args = string . Format ( "install -OutputDirectory {0} {1}" , packageDirectory , package ) ;
96116 }
97117 else
98118 {
99119 exe = "mono" ;
100- args = string . Format ( "{0} install -OutputDirectory {1} {2}" , nugetExe , PackageDirectory , package ) ;
120+ args = string . Format ( "{0} install -OutputDirectory {1} {2}" , nugetExe , packageDirectory , package ) ;
101121 }
102122
103123 var pi = new ProcessStartInfo ( exe , args )
@@ -133,7 +153,15 @@ private void RestoreNugetPackage(string package)
133153 }
134154 }
135155
136- private readonly string nugetExe ;
137- private readonly ProgressMonitor progressMonitor ;
156+ /// <summary>
157+ /// Download the packages to the temp folder.
158+ /// </summary>
159+ public void InstallPackages ( )
160+ {
161+ foreach ( var package in packageFiles )
162+ {
163+ RestoreNugetPackage ( package . FullName ) ;
164+ }
165+ }
138166 }
139167}
0 commit comments