@@ -30,9 +30,7 @@ public sealed class DependencyManager : IDisposable
3030 private readonly DotNet dotnet ;
3131 private readonly FileContent fileContent ;
3232 private readonly TemporaryDirectory packageDirectory ;
33- private TemporaryDirectory ? razorWorkingDirectory ;
34- private readonly Git git ;
35-
33+ private readonly TemporaryDirectory tempWorkingDirectory ;
3634
3735 /// <summary>
3836 /// Performs C# dependency fetching.
@@ -60,20 +58,21 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
6058 this . progressMonitor . FindingFiles ( srcDir ) ;
6159
6260 packageDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName ) ) ;
63- var allFiles = GetAllFiles ( ) . ToList ( ) ;
64- var smallFiles = allFiles . SelectSmallFiles ( progressMonitor ) . SelectFileNames ( ) ;
65- this . fileContent = new FileContent ( progressMonitor , smallFiles ) ;
66- this . allSources = allFiles . SelectFileNamesByExtension ( ".cs" ) . ToList ( ) ;
67- var allProjects = allFiles . SelectFileNamesByExtension ( ".csproj" ) ;
61+ tempWorkingDirectory = new TemporaryDirectory ( GetTemporaryWorkingDirectory ( ) ) ;
62+
63+ var allFiles = GetAllFiles ( ) ;
64+ var binaryFileExtensions = new HashSet < string > ( new [ ] { ".dll" , ".exe" } ) ; // TODO: add more binary file extensions.
65+ var allNonBinaryFiles = allFiles . Where ( f => ! binaryFileExtensions . Contains ( f . Extension . ToLowerInvariant ( ) ) ) . ToList ( ) ;
66+ var smallNonBinaryFiles = allNonBinaryFiles . SelectSmallFiles ( progressMonitor ) . SelectFileNames ( ) ;
67+ this . fileContent = new FileContent ( progressMonitor , smallNonBinaryFiles ) ;
68+ this . allSources = allNonBinaryFiles . SelectFileNamesByExtension ( ".cs" ) . ToList ( ) ;
69+ var allProjects = allNonBinaryFiles . SelectFileNamesByExtension ( ".csproj" ) ;
6870 var solutions = options . SolutionFile is not null
6971 ? new [ ] { options . SolutionFile }
70- : allFiles . SelectFileNamesByExtension ( ".sln" ) ;
71-
72- // If DLL reference paths are specified on the command-line, use those to discover
73- // assemblies. Otherwise (the default), query the git CLI to determine which DLL files
74- // are tracked as part of the repository.
75- this . git = new Git ( this . progressMonitor ) ;
76- var dllDirNames = options . DllDirs . Count == 0 ? this . git . ListFiles ( "*.dll" ) : options . DllDirs . Select ( Path . GetFullPath ) . ToList ( ) ;
72+ : allNonBinaryFiles . SelectFileNamesByExtension ( ".sln" ) ;
73+ var dllDirNames = options . DllDirs . Count == 0
74+ ? allFiles . SelectFileNamesByExtension ( ".dll" ) . ToList ( )
75+ : options . DllDirs . Select ( Path . GetFullPath ) . ToList ( ) ;
7776
7877 // Find DLLs in the .Net / Asp.Net Framework
7978 if ( options . ScanNetFrameworkDlls )
@@ -106,7 +105,7 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
106105 var restoredProjects = RestoreSolutions ( solutions ) ;
107106 var projects = allProjects . Except ( restoredProjects ) ;
108107 RestoreProjects ( projects ) ;
109- DownloadMissingPackages ( allFiles ) ;
108+ DownloadMissingPackages ( allNonBinaryFiles ) ;
110109 }
111110
112111 assemblyCache = new AssemblyCache ( dllDirNames , progressMonitor ) ;
@@ -134,9 +133,11 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
134133 if ( bool . TryParse ( webViewExtractionOption , out var shouldExtractWebViews ) &&
135134 shouldExtractWebViews )
136135 {
137- GenerateSourceFilesFromWebViews ( allFiles ) ;
136+ GenerateSourceFilesFromWebViews ( allNonBinaryFiles ) ;
138137 }
139138
139+ GenerateSourceFileFromImplicitUsings ( ) ;
140+
140141 progressMonitor . Summary (
141142 AllSourceFiles . Count ( ) ,
142143 ProjectSourceFiles . Count ( ) ,
@@ -149,6 +150,46 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
149150 DateTime . Now - startTime ) ;
150151 }
151152
153+ private void GenerateSourceFileFromImplicitUsings ( )
154+ {
155+ var usings = new HashSet < string > ( ) ;
156+ if ( ! fileContent . UseImplicitUsings )
157+ {
158+ return ;
159+ }
160+
161+ // Hardcoded values from https://learn.microsoft.com/en-us/dotnet/core/project-sdk/overview#implicit-using-directives
162+ usings . UnionWith ( new [ ] { "System" , "System.Collections.Generic" , "System.IO" , "System.Linq" , "System.Net.Http" , "System.Threading" ,
163+ "System.Threading.Tasks" } ) ;
164+
165+ if ( fileContent . UseAspNetDlls )
166+ {
167+ usings . UnionWith ( new [ ] { "System.Net.Http.Json" , "Microsoft.AspNetCore.Builder" , "Microsoft.AspNetCore.Hosting" ,
168+ "Microsoft.AspNetCore.Http" , "Microsoft.AspNetCore.Routing" , "Microsoft.Extensions.Configuration" ,
169+ "Microsoft.Extensions.DependencyInjection" , "Microsoft.Extensions.Hosting" , "Microsoft.Extensions.Logging" } ) ;
170+ }
171+
172+ usings . UnionWith ( fileContent . CustomImplicitUsings ) ;
173+
174+ if ( usings . Count > 0 )
175+ {
176+ var tempDir = GetTemporaryWorkingDirectory ( "implicitUsings" ) ;
177+ var path = Path . Combine ( tempDir , "GlobalUsings.g.cs" ) ;
178+ using ( var writer = new StreamWriter ( path ) )
179+ {
180+ writer . WriteLine ( "// <auto-generated/>" ) ;
181+ writer . WriteLine ( "" ) ;
182+
183+ foreach ( var u in usings . OrderBy ( u => u ) )
184+ {
185+ writer . WriteLine ( $ "global using global::{ u } ;") ;
186+ }
187+ }
188+
189+ this . allSources . Add ( path ) ;
190+ }
191+ }
192+
152193 private void GenerateSourceFilesFromWebViews ( List < FileInfo > allFiles )
153194 {
154195 progressMonitor . LogInfo ( $ "Generating source files from cshtml and razor files.") ;
@@ -165,8 +206,8 @@ private void GenerateSourceFilesFromWebViews(List<FileInfo> allFiles)
165206 try
166207 {
167208 var razor = new Razor ( sdk , dotnet , progressMonitor ) ;
168- razorWorkingDirectory = new TemporaryDirectory ( ComputeTempDirectory ( sourceDir . FullName , "razor" ) ) ;
169- var generatedFiles = razor . GenerateFiles ( views , usedReferences . Keys , razorWorkingDirectory . ToString ( ) ) ;
209+ var targetDir = GetTemporaryWorkingDirectory ( "razor" ) ;
210+ var generatedFiles = razor . GenerateFiles ( views , usedReferences . Keys , targetDir ) ;
170211 this . allSources . AddRange ( generatedFiles ) ;
171212 }
172213 catch ( Exception ex )
@@ -180,24 +221,61 @@ private void GenerateSourceFilesFromWebViews(List<FileInfo> allFiles)
180221
181222 public DependencyManager ( string srcDir ) : this ( srcDir , DependencyOptions . Default , new ConsoleLogger ( Verbosity . Info ) ) { }
182223
183- private IEnumerable < FileInfo > GetAllFiles ( ) =>
184- sourceDir . GetFiles ( "*.*" , new EnumerationOptions { RecurseSubdirectories = true } )
185- . Where ( d => d . Extension != ".dll" && ! options . ExcludesFile ( d . FullName ) ) ;
224+ private IEnumerable < FileInfo > GetAllFiles ( )
225+ {
226+ var files = sourceDir . GetFiles ( "*.*" , new EnumerationOptions { RecurseSubdirectories = true } )
227+ . Where ( d => ! options . ExcludesFile ( d . FullName ) ) ;
228+
229+ if ( options . DotNetPath != null )
230+ {
231+ files = files . Where ( f => ! f . FullName . StartsWith ( options . DotNetPath , StringComparison . OrdinalIgnoreCase ) ) ;
232+ }
233+
234+ return files ;
235+ }
186236
187237 /// <summary>
188238 /// Computes a unique temp directory for the packages associated
189239 /// with this source tree. Use a SHA1 of the directory name.
190240 /// </summary>
191241 /// <returns>The full path of the temp directory.</returns>
192- private static string ComputeTempDirectory ( string srcDir , string subfolderName = "packages" )
242+ private static string ComputeTempDirectory ( string srcDir )
193243 {
194244 var bytes = Encoding . Unicode . GetBytes ( srcDir ) ;
195245 var sha = SHA1 . HashData ( bytes ) ;
196246 var sb = new StringBuilder ( ) ;
197247 foreach ( var b in sha . Take ( 8 ) )
198248 sb . AppendFormat ( "{0:x2}" , b ) ;
199249
200- return Path . Combine ( Path . GetTempPath ( ) , "GitHub" , subfolderName , sb . ToString ( ) ) ;
250+ return Path . Combine ( Path . GetTempPath ( ) , "GitHub" , "packages" , sb . ToString ( ) ) ;
251+ }
252+
253+ private static string GetTemporaryWorkingDirectory ( )
254+ {
255+ var tempFolder = EnvironmentVariables . GetScratchDirectory ( ) ;
256+
257+ if ( string . IsNullOrEmpty ( tempFolder ) )
258+ {
259+ var tempPath = Path . GetTempPath ( ) ;
260+ var name = Guid . NewGuid ( ) . ToString ( "N" ) . ToUpper ( ) ;
261+ tempFolder = Path . Combine ( tempPath , "GitHub" , name ) ;
262+ }
263+
264+ return tempFolder ;
265+ }
266+
267+ /// <summary>
268+ /// Creates a temporary directory with the given subfolder name.
269+ /// The created directory might be inside the repo folder, and it is deleted when the object is disposed.
270+ /// </summary>
271+ /// <param name="subfolder"></param>
272+ /// <returns></returns>
273+ private string GetTemporaryWorkingDirectory ( string subfolder )
274+ {
275+ var temp = Path . Combine ( tempWorkingDirectory . ToString ( ) , subfolder ) ;
276+ Directory . CreateDirectory ( temp ) ;
277+
278+ return temp ;
201279 }
202280
203281 /// <summary>
@@ -424,7 +502,7 @@ private void DownloadMissingPackages(List<FileInfo> allFiles)
424502 foreach ( var package in notYetDownloadedPackages )
425503 {
426504 progressMonitor . NugetInstall ( package ) ;
427- using var tempDir = new TemporaryDirectory ( ComputeTempDirectory ( package ) ) ;
505+ using var tempDir = new TemporaryDirectory ( GetTemporaryWorkingDirectory ( package ) ) ;
428506 var success = dotnet . New ( tempDir . DirInfo . FullName ) ;
429507 if ( ! success )
430508 {
@@ -467,7 +545,7 @@ private void AnalyseSolutions(IEnumerable<string> solutions)
467545 public void Dispose ( )
468546 {
469547 packageDirectory ? . Dispose ( ) ;
470- razorWorkingDirectory ? . Dispose ( ) ;
548+ tempWorkingDirectory ? . Dispose ( ) ;
471549 }
472550 }
473551}
0 commit comments