diff --git a/.editorconfig b/.editorconfig index dd0e093..7637b18 100644 --- a/.editorconfig +++ b/.editorconfig @@ -90,3 +90,6 @@ dotnet_diagnostic.SA1641.severity = none dotnet_diagnostic.SA1642.severity = none dotnet_diagnostic.SA1643.severity = none dotnet_diagnostic.SA1649.severity = none + +# Workaround for https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3503 +dotnet_diagnostic.SA1010.severity = none diff --git a/src/TfvcMigrator/InterceptableCommandHandler.cs b/src/TfvcMigrator/InterceptableCommandHandler.cs index 54f6d81..fedcd7a 100644 --- a/src/TfvcMigrator/InterceptableCommandHandler.cs +++ b/src/TfvcMigrator/InterceptableCommandHandler.cs @@ -86,6 +86,11 @@ public static Delegate Intercept(Delegate @delegate) { generator.Emit(OpCodes.Call, typeof(Task).GetProperty(nameof(Task.CompletedTask), BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly)!.GetMethod!); } + else if (@delegate.Method.ReturnType == typeof(Task)) + { + generator.Emit(OpCodes.Ldc_I4_0); + generator.Emit(OpCodes.Call, typeof(Task).GetMethod(nameof(Task.FromResult), BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly)!.MakeGenericMethod(typeof(int))); + } else { throw new NotImplementedException(); diff --git a/src/TfvcMigrator/Program.cs b/src/TfvcMigrator/Program.cs index 7ce8f33..4676ddd 100644 --- a/src/TfvcMigrator/Program.cs +++ b/src/TfvcMigrator/Program.cs @@ -12,7 +12,7 @@ namespace TfvcMigrator; public static class Program { - public static Task Main(string[] args) + public static Task Main(string[] args) { var command = new RootCommand("Migrates TFVC source history to idiomatic Git history while preserving branch topology.") { @@ -58,7 +58,7 @@ private static RootPathChange ParseRootPathChange(string token) return new RootPathChange(changeset, token[(colonIndex + 1)..]); } - public static async Task MigrateAsync( + public static async Task MigrateAsync( Uri projectCollectionUrl, string rootPath, string authors, @@ -74,17 +74,12 @@ private static RootPathChange ParseRootPathChange(string token) new[] { outDir, PathUtils.GetLeaf(rootPath), projectCollectionUrl.Segments.LastOrDefault() } .First(name => !string.IsNullOrEmpty(name))!); - Directory.CreateDirectory(outputDirectory); - if (Directory.GetFileSystemEntries(outputDirectory).Any()) - { - Console.WriteLine($"Cannot create Git repository at {outputDirectory} because the directory is not empty."); - return; - } + using var repo = InitRepository(outputDirectory); + if (repo is null) + return 1; var authorsLookup = LoadAuthors(authors); - using var repo = new Repository(Repository.Init(outputDirectory)); - Console.WriteLine("Connecting..."); using var connection = new VssConnection( @@ -131,7 +126,7 @@ private static RootPathChange ParseRootPathChange(string token) Console.WriteLine("An entry must be added to the authors file for each of the following TFVC users:"); foreach (var user in unmappedAuthors) Console.WriteLine(user); - return; + return 1; } Console.WriteLine("Downloading changesets and converting to commits..."); @@ -336,6 +331,33 @@ private static RootPathChange ParseRootPathChange(string token) } Console.WriteLine($"\rAll {changesets.Count} changesets migrated successfully."); + return 0; + } + + private static Repository? InitRepository(string outputDirectory) + { + Directory.CreateDirectory(outputDirectory); + + var existingFileSystemEntries = Directory.GetFileSystemEntries(outputDirectory); + if (!existingFileSystemEntries.Any()) + return new Repository(Repository.Init(outputDirectory)); + + if (existingFileSystemEntries is not [var singleFileSystemEntry] + || !".git".Equals(Path.GetFileName(singleFileSystemEntry), StringComparison.OrdinalIgnoreCase)) + { + Console.WriteLine($"Cannot create Git repository at {outputDirectory} because the directory is not empty."); + return null; + } + + var repository = new Repository(singleFileSystemEntry); + if (repository.ObjectDatabase.Any()) + { + repository.Dispose(); + Console.WriteLine($"A Git repository at {outputDirectory} already exists and is not empty."); + return null; + } + + return repository; } private static ImmutableDictionary> MapItemsToDownloadSources( diff --git a/src/TfvcMigrator/TfvcMigrator.csproj b/src/TfvcMigrator/TfvcMigrator.csproj index be4a577..d90c439 100644 --- a/src/TfvcMigrator/TfvcMigrator.csproj +++ b/src/TfvcMigrator/TfvcMigrator.csproj @@ -3,6 +3,7 @@ Exe net6.0 + 11 enable true