@@ -30,9 +30,7 @@ public sealed class DependencyManager : IDisposable
30
30
private readonly DotNet dotnet ;
31
31
private readonly FileContent fileContent ;
32
32
private readonly TemporaryDirectory packageDirectory ;
33
- private TemporaryDirectory ? razorWorkingDirectory ;
34
- private readonly Git git ;
35
-
33
+ private readonly TemporaryDirectory tempWorkingDirectory ;
36
34
37
35
/// <summary>
38
36
/// Performs C# dependency fetching.
@@ -60,20 +58,21 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
60
58
this . progressMonitor . FindingFiles ( srcDir ) ;
61
59
62
60
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" ) ;
68
70
var solutions = options . SolutionFile is not null
69
71
? 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 ( ) ;
77
76
78
77
// Find DLLs in the .Net / Asp.Net Framework
79
78
if ( options . ScanNetFrameworkDlls )
@@ -106,7 +105,7 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
106
105
var restoredProjects = RestoreSolutions ( solutions ) ;
107
106
var projects = allProjects . Except ( restoredProjects ) ;
108
107
RestoreProjects ( projects ) ;
109
- DownloadMissingPackages ( allFiles ) ;
108
+ DownloadMissingPackages ( allNonBinaryFiles ) ;
110
109
}
111
110
112
111
assemblyCache = new AssemblyCache ( dllDirNames , progressMonitor ) ;
@@ -134,9 +133,11 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
134
133
if ( bool . TryParse ( webViewExtractionOption , out var shouldExtractWebViews ) &&
135
134
shouldExtractWebViews )
136
135
{
137
- GenerateSourceFilesFromWebViews ( allFiles ) ;
136
+ GenerateSourceFilesFromWebViews ( allNonBinaryFiles ) ;
138
137
}
139
138
139
+ GenerateSourceFileFromImplicitUsings ( ) ;
140
+
140
141
progressMonitor . Summary (
141
142
AllSourceFiles . Count ( ) ,
142
143
ProjectSourceFiles . Count ( ) ,
@@ -149,6 +150,46 @@ public DependencyManager(string srcDir, IDependencyOptions options, ILogger logg
149
150
DateTime . Now - startTime ) ;
150
151
}
151
152
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
+
152
193
private void GenerateSourceFilesFromWebViews ( List < FileInfo > allFiles )
153
194
{
154
195
progressMonitor . LogInfo ( $ "Generating source files from cshtml and razor files.") ;
@@ -165,8 +206,8 @@ private void GenerateSourceFilesFromWebViews(List<FileInfo> allFiles)
165
206
try
166
207
{
167
208
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 ) ;
170
211
this . allSources . AddRange ( generatedFiles ) ;
171
212
}
172
213
catch ( Exception ex )
@@ -180,24 +221,61 @@ private void GenerateSourceFilesFromWebViews(List<FileInfo> allFiles)
180
221
181
222
public DependencyManager ( string srcDir ) : this ( srcDir , DependencyOptions . Default , new ConsoleLogger ( Verbosity . Info ) ) { }
182
223
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
+ }
186
236
187
237
/// <summary>
188
238
/// Computes a unique temp directory for the packages associated
189
239
/// with this source tree. Use a SHA1 of the directory name.
190
240
/// </summary>
191
241
/// <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 )
193
243
{
194
244
var bytes = Encoding . Unicode . GetBytes ( srcDir ) ;
195
245
var sha = SHA1 . HashData ( bytes ) ;
196
246
var sb = new StringBuilder ( ) ;
197
247
foreach ( var b in sha . Take ( 8 ) )
198
248
sb . AppendFormat ( "{0:x2}" , b ) ;
199
249
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 ;
201
279
}
202
280
203
281
/// <summary>
@@ -424,7 +502,7 @@ private void DownloadMissingPackages(List<FileInfo> allFiles)
424
502
foreach ( var package in notYetDownloadedPackages )
425
503
{
426
504
progressMonitor . NugetInstall ( package ) ;
427
- using var tempDir = new TemporaryDirectory ( ComputeTempDirectory ( package ) ) ;
505
+ using var tempDir = new TemporaryDirectory ( GetTemporaryWorkingDirectory ( package ) ) ;
428
506
var success = dotnet . New ( tempDir . DirInfo . FullName ) ;
429
507
if ( ! success )
430
508
{
@@ -467,7 +545,7 @@ private void AnalyseSolutions(IEnumerable<string> solutions)
467
545
public void Dispose ( )
468
546
{
469
547
packageDirectory ? . Dispose ( ) ;
470
- razorWorkingDirectory ? . Dispose ( ) ;
548
+ tempWorkingDirectory ? . Dispose ( ) ;
471
549
}
472
550
}
473
551
}
0 commit comments