22using System . Collections . Generic ;
33using System . Diagnostics ;
44using System . IO ;
5+ using System . Linq ;
6+ using System . Text . RegularExpressions ;
57using Semmle . Util ;
68
79namespace Semmle . Extraction . CSharp . DependencyFetching
810{
911 /// <summary>
1012 /// Utilities to run the "dotnet" command.
1113 /// </summary>
12- internal class DotNet : IDotNet
14+ internal partial class DotNet : IDotNet
1315 {
1416 private readonly ProgressMonitor progressMonitor ;
1517 private readonly string dotnet ;
@@ -41,7 +43,7 @@ private ProcessStartInfo MakeDotnetStartInfo(string args, bool redirectStandardO
4143 private bool RunCommand ( string args )
4244 {
4345 progressMonitor . RunningProcess ( $ "{ dotnet } { args } ") ;
44- using var proc = Process . Start ( this . MakeDotnetStartInfo ( args , redirectStandardOutput : false ) ) ;
46+ using var proc = Process . Start ( MakeDotnetStartInfo ( args , redirectStandardOutput : false ) ) ;
4547 proc ? . WaitForExit ( ) ;
4648 var exitCode = proc ? . ExitCode ?? - 1 ;
4749 if ( exitCode != 0 )
@@ -52,14 +54,51 @@ private bool RunCommand(string args)
5254 return true ;
5355 }
5456
55- public bool RestoreToDirectory ( string projectOrSolutionFile , string packageDirectory , string ? pathToNugetConfig = null )
57+ private bool RunCommand ( string args , out IList < string > output )
5658 {
57- var args = $ "restore --no-dependencies \" { projectOrSolutionFile } \" --packages \" { packageDirectory } \" /p:DisableImplicitNuGetFallbackFolder=true";
59+ progressMonitor . RunningProcess ( $ "{ dotnet } { args } ") ;
60+ var pi = MakeDotnetStartInfo ( args , redirectStandardOutput : true ) ;
61+ var exitCode = pi . ReadOutput ( out output ) ;
62+ if ( exitCode != 0 )
63+ {
64+ progressMonitor . CommandFailed ( dotnet , args , exitCode ) ;
65+ return false ;
66+ }
67+ return true ;
68+ }
69+
70+ private static string GetRestoreArgs ( string projectOrSolutionFile , string packageDirectory ) =>
71+ $ "restore --no-dependencies \" { projectOrSolutionFile } \" --packages \" { packageDirectory } \" /p:DisableImplicitNuGetFallbackFolder=true";
72+
73+ public bool RestoreProjectToDirectory ( string projectFile , string packageDirectory , string ? pathToNugetConfig = null )
74+ {
75+ var args = GetRestoreArgs ( projectFile , packageDirectory ) ;
5876 if ( pathToNugetConfig != null )
77+ {
5978 args += $ " --configfile \" { pathToNugetConfig } \" ";
79+ }
6080 return RunCommand ( args ) ;
6181 }
6282
83+ public bool RestoreSolutionToDirectory ( string solutionFile , string packageDirectory , out IList < string > projects )
84+ {
85+ var args = GetRestoreArgs ( solutionFile , packageDirectory ) ;
86+ args += " --verbosity normal" ;
87+ if ( RunCommand ( args , out var output ) )
88+ {
89+ var regex = RestoreProjectRegex ( ) ;
90+ projects = output
91+ . Select ( line => regex . Match ( line ) )
92+ . Where ( match => match . Success )
93+ . Select ( match => match . Groups [ 1 ] . Value )
94+ . ToList ( ) ;
95+ return true ;
96+ }
97+
98+ projects = new List < string > ( ) ;
99+ return false ;
100+ }
101+
63102 public bool New ( string folder )
64103 {
65104 var args = $ "new console --no-restore --output \" { folder } \" ";
@@ -78,22 +117,21 @@ public bool AddPackage(string folder, string package)
78117
79118 private IList < string > GetListed ( string args , string artifact )
80119 {
81- progressMonitor . RunningProcess ( $ "{ dotnet } { args } ") ;
82- var pi = this . MakeDotnetStartInfo ( args , redirectStandardOutput : true ) ;
83- var exitCode = pi . ReadOutput ( out var artifacts ) ;
84- if ( exitCode != 0 )
120+ if ( RunCommand ( args , out var artifacts ) )
85121 {
86- progressMonitor . CommandFailed ( dotnet , args , exitCode ) ;
87- return new List < string > ( ) ;
122+ progressMonitor . LogInfo ( $ "Found { artifact } s: { string . Join ( " \n " , artifacts ) } " ) ;
123+ return artifacts ;
88124 }
89- progressMonitor . LogInfo ( $ "Found { artifact } s: { string . Join ( "\n " , artifacts ) } ") ;
90- return artifacts ;
125+ return new List < string > ( ) ;
91126 }
92127
93128 public bool Exec ( string execArgs )
94129 {
95130 var args = $ "exec { execArgs } ";
96131 return RunCommand ( args ) ;
97132 }
133+
134+ [ GeneratedRegex ( "Restored\\ s+(.+\\ .csproj)" , RegexOptions . Compiled ) ]
135+ private static partial Regex RestoreProjectRegex ( ) ;
98136 }
99137}
0 commit comments