From 0bffff24a895212ac01aea62f875c0a983a38b8b Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Wed, 26 Jun 2024 09:23:09 +0700 Subject: [PATCH 01/10] Add MkFwData program --- src/MkFwData/.editorconfig | 27 ++++++++++++++ src/MkFwData/.gitattributes | 1 + src/MkFwData/MkFwData.csproj | 28 ++++++++++++++ src/MkFwData/Program.cs | 72 ++++++++++++++++++++++++++++++++++++ 4 files changed, 128 insertions(+) create mode 100644 src/MkFwData/.editorconfig create mode 100644 src/MkFwData/.gitattributes create mode 100644 src/MkFwData/MkFwData.csproj create mode 100644 src/MkFwData/Program.cs diff --git a/src/MkFwData/.editorconfig b/src/MkFwData/.editorconfig new file mode 100644 index 00000000..d4047b80 --- /dev/null +++ b/src/MkFwData/.editorconfig @@ -0,0 +1,27 @@ +# Copyright (c) 2016-2021 SIL International +# This software is licensed under the MIT license (http://opensource.org/licenses/MIT) + +root = false + +# Defaults +[*] +indent_style = space +indent_size = tab +tab_width = 4 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +max_line_length = 98 + +[*.cs] +indent_style = space +tab_width = 4 + +# Settings Visual Studio uses for the generated files +[*.{csproj,resx,settings,targets,vcxproj*,vdproj,xml,yml,props,md}] +indent_style = space +indent_size = 2 + +# Generated file +[*.sln] +end_of_line = crlf diff --git a/src/MkFwData/.gitattributes b/src/MkFwData/.gitattributes new file mode 100644 index 00000000..cf3363d0 --- /dev/null +++ b/src/MkFwData/.gitattributes @@ -0,0 +1 @@ +* text=auto whitespace=space-before-tab,tab-in-indent,blank-at-eol,tabwidth=4 diff --git a/src/MkFwData/MkFwData.csproj b/src/MkFwData/MkFwData.csproj new file mode 100644 index 00000000..e1e5cf02 --- /dev/null +++ b/src/MkFwData/MkFwData.csproj @@ -0,0 +1,28 @@ + + + + Exe + net8.0 + net8.0 + enable + enable + true + $(MSBuildProjectDirectory) + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/MkFwData/Program.cs b/src/MkFwData/Program.cs new file mode 100644 index 00000000..dae97645 --- /dev/null +++ b/src/MkFwData/Program.cs @@ -0,0 +1,72 @@ +using Chorus.VcsDrivers.Mercurial; +using SIL.Progress; +using System.CommandLine; + +class Program +{ + static async Task Main(string[] args) + { + var rootCommand = new RootCommand("Make .fwdata file"); + + var verboseOption = new Option( + ["--verbose", "-v"], + "Display verbose output" + ); + rootCommand.AddGlobalOption(verboseOption); + + var quietOption = new Option( + ["--quiet", "-q"], + "Suppress all output (overrides --verbose if present)" + ); + rootCommand.AddGlobalOption(quietOption); + + var file = new Argument( + "file", + "Name of .fwdata file to create" + ); + rootCommand.Add(file); + + var hgRevOption = new Option( + ["--rev", "-r"], + "Revision to check out (default \"tip\")" + ); + hgRevOption.SetDefaultValue("tip"); + rootCommand.Add(hgRevOption); + + var cleanupOption = new Option( + ["--cleanup", "-c"], + "Clean repository after creating .fwdata file (deletes every other file except .fwdata)" + ); + rootCommand.Add(cleanupOption); + + rootCommand.SetHandler(Run, file, verboseOption, quietOption, hgRevOption, cleanupOption); + + return await rootCommand.InvokeAsync(args); + } + + static Task Run(FileSystemInfo file, bool verbose, bool quiet, string rev, bool cleanup) + { + IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); + progress.ShowVerbose = verbose; + bool isDir = file.Exists && (file.Attributes & FileAttributes.Directory) != 0; + string name = isDir ? Path.Join(file.FullName, file.Name + ".fwdata") : file.FullName; + string dir = isDir ? file.FullName : new FileInfo(file.FullName).Directory!.FullName; + progress.WriteMessage("Checking out {0}", rev); + var result = HgRunner.Run($"hg checkout {rev}", dir, 30, progress); + if (result.ExitCode != 0) + { + progress.WriteMessage("Could not find Mercurial repo; please check filename"); + return Task.FromResult(result.ExitCode); + } + progress.WriteVerbose("Creating {0} ...", name); + LfMergeBridge.LfMergeBridge.ReassembleFwdataFile(progress, writeVerbose: true, name); + progress.WriteMessage("Created {0}", name); + if (cleanup) + { + progress.WriteVerbose("Cleaning up..."); + HgRunner.Run($"hg checkout null", dir, 30, progress); + HgRunner.Run($"hg purge --no-confirm --exclude *.fwdata --exclude hgRunner.log", dir, 30, progress); + } + return Task.FromResult(0); + } +} From d2876ca5facf3f3e448acb3fc105f36196c3e4b3 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Wed, 26 Jun 2024 12:47:40 +0700 Subject: [PATCH 02/10] Add SplitFwData program --- src/SplitFwData/.editorconfig | 27 ++++++++++++++ src/SplitFwData/.gitattributes | 1 + src/SplitFwData/Program.cs | 58 ++++++++++++++++++++++++++++++ src/SplitFwData/SplitFwData.csproj | 28 +++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 src/SplitFwData/.editorconfig create mode 100644 src/SplitFwData/.gitattributes create mode 100644 src/SplitFwData/Program.cs create mode 100644 src/SplitFwData/SplitFwData.csproj diff --git a/src/SplitFwData/.editorconfig b/src/SplitFwData/.editorconfig new file mode 100644 index 00000000..d4047b80 --- /dev/null +++ b/src/SplitFwData/.editorconfig @@ -0,0 +1,27 @@ +# Copyright (c) 2016-2021 SIL International +# This software is licensed under the MIT license (http://opensource.org/licenses/MIT) + +root = false + +# Defaults +[*] +indent_style = space +indent_size = tab +tab_width = 4 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +max_line_length = 98 + +[*.cs] +indent_style = space +tab_width = 4 + +# Settings Visual Studio uses for the generated files +[*.{csproj,resx,settings,targets,vcxproj*,vdproj,xml,yml,props,md}] +indent_style = space +indent_size = 2 + +# Generated file +[*.sln] +end_of_line = crlf diff --git a/src/SplitFwData/.gitattributes b/src/SplitFwData/.gitattributes new file mode 100644 index 00000000..cf3363d0 --- /dev/null +++ b/src/SplitFwData/.gitattributes @@ -0,0 +1 @@ +* text=auto whitespace=space-before-tab,tab-in-indent,blank-at-eol,tabwidth=4 diff --git a/src/SplitFwData/Program.cs b/src/SplitFwData/Program.cs new file mode 100644 index 00000000..1792cef1 --- /dev/null +++ b/src/SplitFwData/Program.cs @@ -0,0 +1,58 @@ +using Chorus.VcsDrivers.Mercurial; +using SIL.Progress; +using System.CommandLine; + +class Program +{ + static async Task Main(string[] args) + { + var rootCommand = new RootCommand("Make .fwdata file"); + + var verboseOption = new Option( + ["--verbose", "-v"], + "Display verbose output" + ); + rootCommand.AddGlobalOption(verboseOption); + + var quietOption = new Option( + ["--quiet", "-q"], + "Suppress all output (overrides --verbose if present)" + ); + rootCommand.AddGlobalOption(quietOption); + + var file = new Argument( + "file", + "Name of .fwdata file to split" + ); + rootCommand.Add(file); + + var cleanupOption = new Option( + ["--cleanup", "-c"], + "Delete .fwdata file after splitting" + ); + rootCommand.Add(cleanupOption); + + rootCommand.SetHandler(Run, file, verboseOption, quietOption, cleanupOption); + + return await rootCommand.InvokeAsync(args); + } + + static Task Run(FileSystemInfo file, bool verbose, bool quiet, bool cleanup) + { + IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); + progress.ShowVerbose = verbose; + bool isDir = file.Exists && (file.Attributes & FileAttributes.Directory) != 0; + string name = isDir ? Path.Join(file.FullName, file.Name + ".fwdata") : file.FullName; + string dir = isDir ? file.FullName : new FileInfo(file.FullName).Directory!.FullName; + progress.WriteVerbose("Splitting {0} ...", name); + LfMergeBridge.LfMergeBridge.DisassembleFwdataFile(progress, writeVerbose: true, name); + progress.WriteMessage("Finished splitting {0}", name); + if (cleanup) + { + progress.WriteVerbose("Cleaning up..."); + var fwdataFile = new FileInfo(name); + if (fwdataFile.Exists) { fwdataFile.Delete(); progress.WriteVerbose("Deleted {0}", fwdataFile.FullName); } else { progress.WriteVerbose("File not found, so not deleting: {0}", fwdataFile.FullName); } + } + return Task.FromResult(0); + } +} diff --git a/src/SplitFwData/SplitFwData.csproj b/src/SplitFwData/SplitFwData.csproj new file mode 100644 index 00000000..e1e5cf02 --- /dev/null +++ b/src/SplitFwData/SplitFwData.csproj @@ -0,0 +1,28 @@ + + + + Exe + net8.0 + net8.0 + enable + enable + true + $(MSBuildProjectDirectory) + + + + + + + + + + + + + + + + + + \ No newline at end of file From 7d5899dd457d17e98f27f8efeee89238db30c8c6 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Wed, 26 Jun 2024 14:17:10 +0700 Subject: [PATCH 03/10] Add MkFwData and SplitFwData to .sln file --- FLExBridge.sln | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/FLExBridge.sln b/FLExBridge.sln index 78a2e43e..daa6e8a1 100644 --- a/FLExBridge.sln +++ b/FLExBridge.sln @@ -52,6 +52,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LfMergeBridgeTestApp", "src EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LfMergeBridgeTests", "src\LfMergeBridgeTests\LfMergeBridgeTests.csproj", "{6CB1246D-956A-4759-AA13-D434CBB383FE}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MkFwData", "src\MkFwData\MkFwData.csproj", "{5CDB086A-79DE-4EF4-BB48-4AEAEEB0827B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SplitFwData", "src\SplitFwData\SplitFwData.csproj", "{23DF39D2-5C50-4832-A64E-022396430390}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiftFileCheckerApp", "src\LiftFileCheckerApp\LiftFileCheckerApp.csproj", "{30AA046B-5E14-408C-89EF-8601BB27FB32}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibTriboroughBridge-ChorusPluginTests", "src\LibTriboroughBridge-ChorusPluginTests\LibTriboroughBridge-ChorusPluginTests.csproj", "{AA6CC4E2-6FD8-4B30-99EC-A446E9CAA176}" @@ -124,6 +128,14 @@ Global {6CB1246D-956A-4759-AA13-D434CBB383FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {6CB1246D-956A-4759-AA13-D434CBB383FE}.Release|Any CPU.ActiveCfg = Release|Any CPU {6CB1246D-956A-4759-AA13-D434CBB383FE}.Release|Any CPU.Build.0 = Release|Any CPU + {5CDB086A-79DE-4EF4-BB48-4AEAEEB0827B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5CDB086A-79DE-4EF4-BB48-4AEAEEB0827B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5CDB086A-79DE-4EF4-BB48-4AEAEEB0827B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5CDB086A-79DE-4EF4-BB48-4AEAEEB0827B}.Release|Any CPU.Build.0 = Release|Any CPU + {23DF39D2-5C50-4832-A64E-022396430390}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {23DF39D2-5C50-4832-A64E-022396430390}.Debug|Any CPU.Build.0 = Debug|Any CPU + {23DF39D2-5C50-4832-A64E-022396430390}.Release|Any CPU.ActiveCfg = Release|Any CPU + {23DF39D2-5C50-4832-A64E-022396430390}.Release|Any CPU.Build.0 = Release|Any CPU {30AA046B-5E14-408C-89EF-8601BB27FB32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {30AA046B-5E14-408C-89EF-8601BB27FB32}.Debug|Any CPU.Build.0 = Debug|Any CPU {30AA046B-5E14-408C-89EF-8601BB27FB32}.Release|Any CPU.ActiveCfg = Release|Any CPU From 2bde4c6183f16261312f6d2bf87db54c75f2531f Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Wed, 26 Jun 2024 16:08:48 +0700 Subject: [PATCH 04/10] Better handling of .fwdata filenames --- src/MkFwData/Program.cs | 47 ++++++++++++++++++++++++++++---------- src/SplitFwData/Program.cs | 32 ++++++++++++++++++++------ 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/MkFwData/Program.cs b/src/MkFwData/Program.cs index dae97645..b7203743 100644 --- a/src/MkFwData/Program.cs +++ b/src/MkFwData/Program.cs @@ -20,11 +20,11 @@ static async Task Main(string[] args) ); rootCommand.AddGlobalOption(quietOption); - var file = new Argument( + var filename = new Argument( "file", - "Name of .fwdata file to create" + "Name of .fwdata file to create, or directory to create it in" ); - rootCommand.Add(file); + rootCommand.Add(filename); var hgRevOption = new Option( ["--rev", "-r"], @@ -39,23 +39,46 @@ static async Task Main(string[] args) ); rootCommand.Add(cleanupOption); - rootCommand.SetHandler(Run, file, verboseOption, quietOption, hgRevOption, cleanupOption); + rootCommand.SetHandler(Run, filename, verboseOption, quietOption, hgRevOption, cleanupOption); return await rootCommand.InvokeAsync(args); } - static Task Run(FileSystemInfo file, bool verbose, bool quiet, string rev, bool cleanup) + static FileInfo LocateFwDataFile(string input) + { + if (Directory.Exists(input)) { + var dirInfo = new DirectoryInfo(input); + var fname = dirInfo.Name + ".fwdata"; + return new FileInfo(Path.Join(input, fname)); + } else if (File.Exists(input)) { + return new FileInfo(input); + } else if (File.Exists(input + ".fwdata")) { + return new FileInfo(input + ".fwdata"); + } else { + if (input.EndsWith(".fwdata")) return new FileInfo(input); + return new FileInfo(input + ".fwdata"); + } + } + + static Task Run(string filename, bool verbose, bool quiet, string rev, bool cleanup) { IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); progress.ShowVerbose = verbose; - bool isDir = file.Exists && (file.Attributes & FileAttributes.Directory) != 0; - string name = isDir ? Path.Join(file.FullName, file.Name + ".fwdata") : file.FullName; - string dir = isDir ? file.FullName : new FileInfo(file.FullName).Directory!.FullName; + var file = LocateFwDataFile(filename); + if (file.Exists) { + progress.WriteWarning("File {0} already exists and will be overwritten", file.FullName); + } + var dir = file.Directory; + if (dir == null || !dir.Exists) { + progress.WriteError("Could not find directory {0}. MkFwData needs a Mercurial repo to work with.", dir?.FullName ?? "(null)"); + return Task.FromResult(1); + } + string name = file.FullName; progress.WriteMessage("Checking out {0}", rev); - var result = HgRunner.Run($"hg checkout {rev}", dir, 30, progress); + var result = HgRunner.Run($"hg checkout {rev}", dir.FullName, 30, progress); if (result.ExitCode != 0) { - progress.WriteMessage("Could not find Mercurial repo; please check filename"); + progress.WriteMessage("Could not find Mercurial repo in directory {0}. MkFwData needs a Mercurial repo to work with.", dir.FullName ?? "(null)"); return Task.FromResult(result.ExitCode); } progress.WriteVerbose("Creating {0} ...", name); @@ -64,8 +87,8 @@ static Task Run(FileSystemInfo file, bool verbose, bool quiet, string rev, if (cleanup) { progress.WriteVerbose("Cleaning up..."); - HgRunner.Run($"hg checkout null", dir, 30, progress); - HgRunner.Run($"hg purge --no-confirm --exclude *.fwdata --exclude hgRunner.log", dir, 30, progress); + HgRunner.Run($"hg checkout null", dir.FullName, 30, progress); + HgRunner.Run($"hg purge --no-confirm --exclude *.fwdata --exclude hgRunner.log", dir.FullName, 30, progress); } return Task.FromResult(0); } diff --git a/src/SplitFwData/Program.cs b/src/SplitFwData/Program.cs index 1792cef1..110a6f09 100644 --- a/src/SplitFwData/Program.cs +++ b/src/SplitFwData/Program.cs @@ -20,11 +20,11 @@ static async Task Main(string[] args) ); rootCommand.AddGlobalOption(quietOption); - var file = new Argument( + var filename = new Argument( "file", "Name of .fwdata file to split" ); - rootCommand.Add(file); + rootCommand.Add(filename); var cleanupOption = new Option( ["--cleanup", "-c"], @@ -32,18 +32,36 @@ static async Task Main(string[] args) ); rootCommand.Add(cleanupOption); - rootCommand.SetHandler(Run, file, verboseOption, quietOption, cleanupOption); + rootCommand.SetHandler(Run, filename, verboseOption, quietOption, cleanupOption); return await rootCommand.InvokeAsync(args); } - static Task Run(FileSystemInfo file, bool verbose, bool quiet, bool cleanup) + static FileInfo? LocateFwDataFile(string input) + { + if (Directory.Exists(input)) { + var dirInfo = new DirectoryInfo(input); + var fname = dirInfo.Name + ".fwdata"; + return new FileInfo(Path.Join(input, fname)); + } else if (File.Exists(input)) { + return new FileInfo(input); + } else if (File.Exists(input + ".fwdata")) { + return new FileInfo(input + ".fwdata"); + } else { + return null; + } + } + + static Task Run(string filename, bool verbose, bool quiet, bool cleanup) { IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); progress.ShowVerbose = verbose; - bool isDir = file.Exists && (file.Attributes & FileAttributes.Directory) != 0; - string name = isDir ? Path.Join(file.FullName, file.Name + ".fwdata") : file.FullName; - string dir = isDir ? file.FullName : new FileInfo(file.FullName).Directory!.FullName; + var file = LocateFwDataFile(filename); + if (file == null || !file.Exists) { + progress.WriteError("Could not find {0}", filename); + return Task.FromResult(1); + } + string name = file.FullName; progress.WriteVerbose("Splitting {0} ...", name); LfMergeBridge.LfMergeBridge.DisassembleFwdataFile(progress, writeVerbose: true, name); progress.WriteMessage("Finished splitting {0}", name); From 525996ea8131366b7cf2f59612a9f105fe58bc90 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Fri, 18 Oct 2024 15:19:32 +0700 Subject: [PATCH 05/10] Combine MkFwData and SplitFwData into one binary Will make for smaller downloads if we make standalone executables. --- FLExBridge.sln | 6 --- src/MkFwData/Program.cs | 71 +++++++++++++++++++++++----- src/SplitFwData/.editorconfig | 27 ----------- src/SplitFwData/.gitattributes | 1 - src/SplitFwData/Program.cs | 76 ------------------------------ src/SplitFwData/SplitFwData.csproj | 28 ----------- 6 files changed, 60 insertions(+), 149 deletions(-) delete mode 100644 src/SplitFwData/.editorconfig delete mode 100644 src/SplitFwData/.gitattributes delete mode 100644 src/SplitFwData/Program.cs delete mode 100644 src/SplitFwData/SplitFwData.csproj diff --git a/FLExBridge.sln b/FLExBridge.sln index daa6e8a1..aef1ac96 100644 --- a/FLExBridge.sln +++ b/FLExBridge.sln @@ -54,8 +54,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LfMergeBridgeTests", "src\L EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MkFwData", "src\MkFwData\MkFwData.csproj", "{5CDB086A-79DE-4EF4-BB48-4AEAEEB0827B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SplitFwData", "src\SplitFwData\SplitFwData.csproj", "{23DF39D2-5C50-4832-A64E-022396430390}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LiftFileCheckerApp", "src\LiftFileCheckerApp\LiftFileCheckerApp.csproj", "{30AA046B-5E14-408C-89EF-8601BB27FB32}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibTriboroughBridge-ChorusPluginTests", "src\LibTriboroughBridge-ChorusPluginTests\LibTriboroughBridge-ChorusPluginTests.csproj", "{AA6CC4E2-6FD8-4B30-99EC-A446E9CAA176}" @@ -132,10 +130,6 @@ Global {5CDB086A-79DE-4EF4-BB48-4AEAEEB0827B}.Debug|Any CPU.Build.0 = Debug|Any CPU {5CDB086A-79DE-4EF4-BB48-4AEAEEB0827B}.Release|Any CPU.ActiveCfg = Release|Any CPU {5CDB086A-79DE-4EF4-BB48-4AEAEEB0827B}.Release|Any CPU.Build.0 = Release|Any CPU - {23DF39D2-5C50-4832-A64E-022396430390}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {23DF39D2-5C50-4832-A64E-022396430390}.Debug|Any CPU.Build.0 = Debug|Any CPU - {23DF39D2-5C50-4832-A64E-022396430390}.Release|Any CPU.ActiveCfg = Release|Any CPU - {23DF39D2-5C50-4832-A64E-022396430390}.Release|Any CPU.Build.0 = Release|Any CPU {30AA046B-5E14-408C-89EF-8601BB27FB32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {30AA046B-5E14-408C-89EF-8601BB27FB32}.Debug|Any CPU.Build.0 = Debug|Any CPU {30AA046B-5E14-408C-89EF-8601BB27FB32}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/src/MkFwData/Program.cs b/src/MkFwData/Program.cs index b7203743..b9d62d95 100644 --- a/src/MkFwData/Program.cs +++ b/src/MkFwData/Program.cs @@ -6,7 +6,7 @@ class Program { static async Task Main(string[] args) { - var rootCommand = new RootCommand("Make .fwdata file"); + var rootCommand = new RootCommand("Make or split .fwdata file"); var verboseOption = new Option( ["--verbose", "-v"], @@ -20,31 +20,46 @@ static async Task Main(string[] args) ); rootCommand.AddGlobalOption(quietOption); + var splitCommand = new Command("split", "Split .fwdata file (push Humpty off the wall)"); + var combineCommand = new Command("combine", "Recombine .fwdata file (put Humpty together again)"); + + rootCommand.Add(splitCommand); + rootCommand.Add(combineCommand); + var filename = new Argument( "file", - "Name of .fwdata file to create, or directory to create it in" + "Name of .fwdata file to create or split, or directory to create/split it in" ); - rootCommand.Add(filename); + splitCommand.Add(filename); + combineCommand.Add(filename); var hgRevOption = new Option( ["--rev", "-r"], "Revision to check out (default \"tip\")" ); hgRevOption.SetDefaultValue("tip"); - rootCommand.Add(hgRevOption); + combineCommand.AddGlobalOption(hgRevOption); var cleanupOption = new Option( ["--cleanup", "-c"], - "Clean repository after creating .fwdata file (deletes every other file except .fwdata)" + "Clean repository after creating .fwdata file (CAUTION: deletes every other file except .fwdata)" ); - rootCommand.Add(cleanupOption); + combineCommand.Add(cleanupOption); - rootCommand.SetHandler(Run, filename, verboseOption, quietOption, hgRevOption, cleanupOption); + combineCommand.SetHandler(CombineFwData, filename, verboseOption, quietOption, hgRevOption, cleanupOption); + + var cleanupOptionForSplit = new Option( + ["--cleanup", "-c"], + "Delete .fwdata file after splitting" + ); + splitCommand.Add(cleanupOptionForSplit); + + splitCommand.SetHandler(SplitFwData, filename, verboseOption, quietOption, cleanupOptionForSplit); return await rootCommand.InvokeAsync(args); } - static FileInfo LocateFwDataFile(string input) + static FileInfo? MaybeLocateFwDataFile(string input) { if (Directory.Exists(input)) { var dirInfo = new DirectoryInfo(input); @@ -55,12 +70,46 @@ static FileInfo LocateFwDataFile(string input) } else if (File.Exists(input + ".fwdata")) { return new FileInfo(input + ".fwdata"); } else { - if (input.EndsWith(".fwdata")) return new FileInfo(input); - return new FileInfo(input + ".fwdata"); + return null; } } - static Task Run(string filename, bool verbose, bool quiet, string rev, bool cleanup) + static FileInfo LocateFwDataFile(string input) + { + var result = MaybeLocateFwDataFile(input); + if (result != null) return result; + if (input.EndsWith(".fwdata")) return new FileInfo(input); + return new FileInfo(input + ".fwdata"); + } + + static Task SplitFwData(string filename, bool verbose, bool quiet, bool cleanup) + { + IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); + progress.ShowVerbose = verbose; + var file = MaybeLocateFwDataFile(filename); + if (file == null || !file.Exists) { + progress.WriteError("Could not find {0}", filename); + return Task.FromResult(1); + } + string name = file.FullName; + progress.WriteVerbose("Splitting {0} ...", name); + LfMergeBridge.LfMergeBridge.DisassembleFwdataFile(progress, writeVerbose: true, name); + progress.WriteMessage("Finished splitting {0}", name); + if (cleanup) + { + progress.WriteVerbose("Cleaning up..."); + var fwdataFile = new FileInfo(name); + if (fwdataFile.Exists) { + fwdataFile.Delete(); + progress.WriteVerbose("Deleted {0}", fwdataFile.FullName); + } else { + progress.WriteVerbose("File not found, so not deleting: {0}", fwdataFile.FullName); + } + } + return Task.FromResult(0); + } + + static Task CombineFwData(string filename, bool verbose, bool quiet, string rev, bool cleanup) { IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); progress.ShowVerbose = verbose; diff --git a/src/SplitFwData/.editorconfig b/src/SplitFwData/.editorconfig deleted file mode 100644 index d4047b80..00000000 --- a/src/SplitFwData/.editorconfig +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2016-2021 SIL International -# This software is licensed under the MIT license (http://opensource.org/licenses/MIT) - -root = false - -# Defaults -[*] -indent_style = space -indent_size = tab -tab_width = 4 -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true -max_line_length = 98 - -[*.cs] -indent_style = space -tab_width = 4 - -# Settings Visual Studio uses for the generated files -[*.{csproj,resx,settings,targets,vcxproj*,vdproj,xml,yml,props,md}] -indent_style = space -indent_size = 2 - -# Generated file -[*.sln] -end_of_line = crlf diff --git a/src/SplitFwData/.gitattributes b/src/SplitFwData/.gitattributes deleted file mode 100644 index cf3363d0..00000000 --- a/src/SplitFwData/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto whitespace=space-before-tab,tab-in-indent,blank-at-eol,tabwidth=4 diff --git a/src/SplitFwData/Program.cs b/src/SplitFwData/Program.cs deleted file mode 100644 index 110a6f09..00000000 --- a/src/SplitFwData/Program.cs +++ /dev/null @@ -1,76 +0,0 @@ -using Chorus.VcsDrivers.Mercurial; -using SIL.Progress; -using System.CommandLine; - -class Program -{ - static async Task Main(string[] args) - { - var rootCommand = new RootCommand("Make .fwdata file"); - - var verboseOption = new Option( - ["--verbose", "-v"], - "Display verbose output" - ); - rootCommand.AddGlobalOption(verboseOption); - - var quietOption = new Option( - ["--quiet", "-q"], - "Suppress all output (overrides --verbose if present)" - ); - rootCommand.AddGlobalOption(quietOption); - - var filename = new Argument( - "file", - "Name of .fwdata file to split" - ); - rootCommand.Add(filename); - - var cleanupOption = new Option( - ["--cleanup", "-c"], - "Delete .fwdata file after splitting" - ); - rootCommand.Add(cleanupOption); - - rootCommand.SetHandler(Run, filename, verboseOption, quietOption, cleanupOption); - - return await rootCommand.InvokeAsync(args); - } - - static FileInfo? LocateFwDataFile(string input) - { - if (Directory.Exists(input)) { - var dirInfo = new DirectoryInfo(input); - var fname = dirInfo.Name + ".fwdata"; - return new FileInfo(Path.Join(input, fname)); - } else if (File.Exists(input)) { - return new FileInfo(input); - } else if (File.Exists(input + ".fwdata")) { - return new FileInfo(input + ".fwdata"); - } else { - return null; - } - } - - static Task Run(string filename, bool verbose, bool quiet, bool cleanup) - { - IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); - progress.ShowVerbose = verbose; - var file = LocateFwDataFile(filename); - if (file == null || !file.Exists) { - progress.WriteError("Could not find {0}", filename); - return Task.FromResult(1); - } - string name = file.FullName; - progress.WriteVerbose("Splitting {0} ...", name); - LfMergeBridge.LfMergeBridge.DisassembleFwdataFile(progress, writeVerbose: true, name); - progress.WriteMessage("Finished splitting {0}", name); - if (cleanup) - { - progress.WriteVerbose("Cleaning up..."); - var fwdataFile = new FileInfo(name); - if (fwdataFile.Exists) { fwdataFile.Delete(); progress.WriteVerbose("Deleted {0}", fwdataFile.FullName); } else { progress.WriteVerbose("File not found, so not deleting: {0}", fwdataFile.FullName); } - } - return Task.FromResult(0); - } -} diff --git a/src/SplitFwData/SplitFwData.csproj b/src/SplitFwData/SplitFwData.csproj deleted file mode 100644 index e1e5cf02..00000000 --- a/src/SplitFwData/SplitFwData.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - Exe - net8.0 - net8.0 - enable - enable - true - $(MSBuildProjectDirectory) - - - - - - - - - - - - - - - - - - \ No newline at end of file From c313bfeef21b98a4db526ddc8912992b17cd99aa Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Fri, 18 Oct 2024 15:38:37 +0700 Subject: [PATCH 06/10] Change .exe name of combined make/split tool --- src/MkFwData/MkFwData.csproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/MkFwData/MkFwData.csproj b/src/MkFwData/MkFwData.csproj index e1e5cf02..580f131a 100644 --- a/src/MkFwData/MkFwData.csproj +++ b/src/MkFwData/MkFwData.csproj @@ -1,6 +1,8 @@ + + fwdata Exe net8.0 net8.0 From 36603a35dc1f926e7c15c4c4b4df619d5a9ec699 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Fri, 18 Oct 2024 15:39:43 +0700 Subject: [PATCH 07/10] Change "combine" command to "build" --- src/MkFwData/Program.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/MkFwData/Program.cs b/src/MkFwData/Program.cs index b9d62d95..fef8e616 100644 --- a/src/MkFwData/Program.cs +++ b/src/MkFwData/Program.cs @@ -21,32 +21,32 @@ static async Task Main(string[] args) rootCommand.AddGlobalOption(quietOption); var splitCommand = new Command("split", "Split .fwdata file (push Humpty off the wall)"); - var combineCommand = new Command("combine", "Recombine .fwdata file (put Humpty together again)"); + var buildCommand = new Command("build", "Rebuild .fwdata file (put Humpty together again)"); rootCommand.Add(splitCommand); - rootCommand.Add(combineCommand); + rootCommand.Add(buildCommand); var filename = new Argument( "file", "Name of .fwdata file to create or split, or directory to create/split it in" ); splitCommand.Add(filename); - combineCommand.Add(filename); + buildCommand.Add(filename); var hgRevOption = new Option( ["--rev", "-r"], "Revision to check out (default \"tip\")" ); hgRevOption.SetDefaultValue("tip"); - combineCommand.AddGlobalOption(hgRevOption); + buildCommand.AddGlobalOption(hgRevOption); var cleanupOption = new Option( ["--cleanup", "-c"], "Clean repository after creating .fwdata file (CAUTION: deletes every other file except .fwdata)" ); - combineCommand.Add(cleanupOption); + buildCommand.Add(cleanupOption); - combineCommand.SetHandler(CombineFwData, filename, verboseOption, quietOption, hgRevOption, cleanupOption); + buildCommand.SetHandler(BuildFwData, filename, verboseOption, quietOption, hgRevOption, cleanupOption); var cleanupOptionForSplit = new Option( ["--cleanup", "-c"], @@ -109,7 +109,7 @@ static Task SplitFwData(string filename, bool verbose, bool quiet, bool cle return Task.FromResult(0); } - static Task CombineFwData(string filename, bool verbose, bool quiet, string rev, bool cleanup) + static Task BuildFwData(string filename, bool verbose, bool quiet, string rev, bool cleanup) { IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); progress.ShowVerbose = verbose; From 708e697fa2c104a39d0dc9809fd12ac9d49cf6b6 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Mon, 21 Oct 2024 15:35:49 +0700 Subject: [PATCH 08/10] Add timeout option, defaulting to 10 minutes --- src/MkFwData/Program.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/MkFwData/Program.cs b/src/MkFwData/Program.cs index fef8e616..07b66101 100644 --- a/src/MkFwData/Program.cs +++ b/src/MkFwData/Program.cs @@ -40,13 +40,20 @@ static async Task Main(string[] args) hgRevOption.SetDefaultValue("tip"); buildCommand.AddGlobalOption(hgRevOption); + var timeoutOption = new Option( + ["--timeout", "-t"], + "Timeout in seconds for Hg commands (default 600)" + ); + timeoutOption.SetDefaultValue(600); + buildCommand.AddGlobalOption(timeoutOption); + var cleanupOption = new Option( ["--cleanup", "-c"], "Clean repository after creating .fwdata file (CAUTION: deletes every other file except .fwdata)" ); buildCommand.Add(cleanupOption); - buildCommand.SetHandler(BuildFwData, filename, verboseOption, quietOption, hgRevOption, cleanupOption); + buildCommand.SetHandler(BuildFwData, filename, verboseOption, quietOption, hgRevOption, timeoutOption, cleanupOption); var cleanupOptionForSplit = new Option( ["--cleanup", "-c"], @@ -109,7 +116,7 @@ static Task SplitFwData(string filename, bool verbose, bool quiet, bool cle return Task.FromResult(0); } - static Task BuildFwData(string filename, bool verbose, bool quiet, string rev, bool cleanup) + static Task BuildFwData(string filename, bool verbose, bool quiet, string rev, int timeout, bool cleanup) { IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); progress.ShowVerbose = verbose; @@ -124,7 +131,7 @@ static Task BuildFwData(string filename, bool verbose, bool quiet, string r } string name = file.FullName; progress.WriteMessage("Checking out {0}", rev); - var result = HgRunner.Run($"hg checkout {rev}", dir.FullName, 30, progress); + var result = HgRunner.Run($"hg checkout {rev}", dir.FullName, timeout, progress); if (result.ExitCode != 0) { progress.WriteMessage("Could not find Mercurial repo in directory {0}. MkFwData needs a Mercurial repo to work with.", dir.FullName ?? "(null)"); @@ -136,8 +143,8 @@ static Task BuildFwData(string filename, bool verbose, bool quiet, string r if (cleanup) { progress.WriteVerbose("Cleaning up..."); - HgRunner.Run($"hg checkout null", dir.FullName, 30, progress); - HgRunner.Run($"hg purge --no-confirm --exclude *.fwdata --exclude hgRunner.log", dir.FullName, 30, progress); + HgRunner.Run($"hg checkout null", dir.FullName, timeout, progress); + HgRunner.Run($"hg purge --no-confirm --exclude *.fwdata --exclude hgRunner.log", dir.FullName, timeout, progress); } return Task.FromResult(0); } From 418f1199d6e1b2be2c27c927ef83cb4320d8e4d4 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Thu, 24 Oct 2024 09:03:40 +0700 Subject: [PATCH 09/10] Trim down .editorconfig to remove duplicated parts We only need to keep the .editorconfig settings that differ from the ones in the root (spaces instead of tabs for indent, add final newline). --- src/MkFwData/.editorconfig | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/src/MkFwData/.editorconfig b/src/MkFwData/.editorconfig index d4047b80..45c84b11 100644 --- a/src/MkFwData/.editorconfig +++ b/src/MkFwData/.editorconfig @@ -1,27 +1,12 @@ -# Copyright (c) 2016-2021 SIL International +# Copyright (c) 2024 SIL International # This software is licensed under the MIT license (http://opensource.org/licenses/MIT) root = false -# Defaults +# Override indent style and final newline defaults for this project only [*] indent_style = space -indent_size = tab -tab_width = 4 -charset = utf-8 -trim_trailing_whitespace = true insert_final_newline = true -max_line_length = 98 [*.cs] indent_style = space -tab_width = 4 - -# Settings Visual Studio uses for the generated files -[*.{csproj,resx,settings,targets,vcxproj*,vdproj,xml,yml,props,md}] -indent_style = space -indent_size = 2 - -# Generated file -[*.sln] -end_of_line = crlf From cda53641966e70e56ae7b9d8ffcbe3ce687c5ee2 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Fri, 25 Oct 2024 16:08:23 +0700 Subject: [PATCH 10/10] Get rid of .editorconfig, use tab indentation To match the style of the rest of this repo, we'll just switch to tab indentation. That makes this nearly a whitespace-only commit, but nobody else is touching this code so it won't create merge conflicts. --- src/MkFwData/.editorconfig | 12 -- src/MkFwData/.gitattributes | 1 - src/MkFwData/Program.cs | 288 ++++++++++++++++++------------------ 3 files changed, 144 insertions(+), 157 deletions(-) delete mode 100644 src/MkFwData/.editorconfig delete mode 100644 src/MkFwData/.gitattributes diff --git a/src/MkFwData/.editorconfig b/src/MkFwData/.editorconfig deleted file mode 100644 index 45c84b11..00000000 --- a/src/MkFwData/.editorconfig +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2024 SIL International -# This software is licensed under the MIT license (http://opensource.org/licenses/MIT) - -root = false - -# Override indent style and final newline defaults for this project only -[*] -indent_style = space -insert_final_newline = true - -[*.cs] -indent_style = space diff --git a/src/MkFwData/.gitattributes b/src/MkFwData/.gitattributes deleted file mode 100644 index cf3363d0..00000000 --- a/src/MkFwData/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto whitespace=space-before-tab,tab-in-indent,blank-at-eol,tabwidth=4 diff --git a/src/MkFwData/Program.cs b/src/MkFwData/Program.cs index 07b66101..419e076b 100644 --- a/src/MkFwData/Program.cs +++ b/src/MkFwData/Program.cs @@ -4,148 +4,148 @@ class Program { - static async Task Main(string[] args) - { - var rootCommand = new RootCommand("Make or split .fwdata file"); - - var verboseOption = new Option( - ["--verbose", "-v"], - "Display verbose output" - ); - rootCommand.AddGlobalOption(verboseOption); - - var quietOption = new Option( - ["--quiet", "-q"], - "Suppress all output (overrides --verbose if present)" - ); - rootCommand.AddGlobalOption(quietOption); - - var splitCommand = new Command("split", "Split .fwdata file (push Humpty off the wall)"); - var buildCommand = new Command("build", "Rebuild .fwdata file (put Humpty together again)"); - - rootCommand.Add(splitCommand); - rootCommand.Add(buildCommand); - - var filename = new Argument( - "file", - "Name of .fwdata file to create or split, or directory to create/split it in" - ); - splitCommand.Add(filename); - buildCommand.Add(filename); - - var hgRevOption = new Option( - ["--rev", "-r"], - "Revision to check out (default \"tip\")" - ); - hgRevOption.SetDefaultValue("tip"); - buildCommand.AddGlobalOption(hgRevOption); - - var timeoutOption = new Option( - ["--timeout", "-t"], - "Timeout in seconds for Hg commands (default 600)" - ); - timeoutOption.SetDefaultValue(600); - buildCommand.AddGlobalOption(timeoutOption); - - var cleanupOption = new Option( - ["--cleanup", "-c"], - "Clean repository after creating .fwdata file (CAUTION: deletes every other file except .fwdata)" - ); - buildCommand.Add(cleanupOption); - - buildCommand.SetHandler(BuildFwData, filename, verboseOption, quietOption, hgRevOption, timeoutOption, cleanupOption); - - var cleanupOptionForSplit = new Option( - ["--cleanup", "-c"], - "Delete .fwdata file after splitting" - ); - splitCommand.Add(cleanupOptionForSplit); - - splitCommand.SetHandler(SplitFwData, filename, verboseOption, quietOption, cleanupOptionForSplit); - - return await rootCommand.InvokeAsync(args); - } - - static FileInfo? MaybeLocateFwDataFile(string input) - { - if (Directory.Exists(input)) { - var dirInfo = new DirectoryInfo(input); - var fname = dirInfo.Name + ".fwdata"; - return new FileInfo(Path.Join(input, fname)); - } else if (File.Exists(input)) { - return new FileInfo(input); - } else if (File.Exists(input + ".fwdata")) { - return new FileInfo(input + ".fwdata"); - } else { - return null; - } - } - - static FileInfo LocateFwDataFile(string input) - { - var result = MaybeLocateFwDataFile(input); - if (result != null) return result; - if (input.EndsWith(".fwdata")) return new FileInfo(input); - return new FileInfo(input + ".fwdata"); - } - - static Task SplitFwData(string filename, bool verbose, bool quiet, bool cleanup) - { - IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); - progress.ShowVerbose = verbose; - var file = MaybeLocateFwDataFile(filename); - if (file == null || !file.Exists) { - progress.WriteError("Could not find {0}", filename); - return Task.FromResult(1); - } - string name = file.FullName; - progress.WriteVerbose("Splitting {0} ...", name); - LfMergeBridge.LfMergeBridge.DisassembleFwdataFile(progress, writeVerbose: true, name); - progress.WriteMessage("Finished splitting {0}", name); - if (cleanup) - { - progress.WriteVerbose("Cleaning up..."); - var fwdataFile = new FileInfo(name); - if (fwdataFile.Exists) { - fwdataFile.Delete(); - progress.WriteVerbose("Deleted {0}", fwdataFile.FullName); - } else { - progress.WriteVerbose("File not found, so not deleting: {0}", fwdataFile.FullName); - } - } - return Task.FromResult(0); - } - - static Task BuildFwData(string filename, bool verbose, bool quiet, string rev, int timeout, bool cleanup) - { - IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); - progress.ShowVerbose = verbose; - var file = LocateFwDataFile(filename); - if (file.Exists) { - progress.WriteWarning("File {0} already exists and will be overwritten", file.FullName); - } - var dir = file.Directory; - if (dir == null || !dir.Exists) { - progress.WriteError("Could not find directory {0}. MkFwData needs a Mercurial repo to work with.", dir?.FullName ?? "(null)"); - return Task.FromResult(1); - } - string name = file.FullName; - progress.WriteMessage("Checking out {0}", rev); - var result = HgRunner.Run($"hg checkout {rev}", dir.FullName, timeout, progress); - if (result.ExitCode != 0) - { - progress.WriteMessage("Could not find Mercurial repo in directory {0}. MkFwData needs a Mercurial repo to work with.", dir.FullName ?? "(null)"); - return Task.FromResult(result.ExitCode); - } - progress.WriteVerbose("Creating {0} ...", name); - LfMergeBridge.LfMergeBridge.ReassembleFwdataFile(progress, writeVerbose: true, name); - progress.WriteMessage("Created {0}", name); - if (cleanup) - { - progress.WriteVerbose("Cleaning up..."); - HgRunner.Run($"hg checkout null", dir.FullName, timeout, progress); - HgRunner.Run($"hg purge --no-confirm --exclude *.fwdata --exclude hgRunner.log", dir.FullName, timeout, progress); - } - return Task.FromResult(0); - } + static async Task Main(string[] args) + { + var rootCommand = new RootCommand("Make or split .fwdata file"); + + var verboseOption = new Option( + ["--verbose", "-v"], + "Display verbose output" + ); + rootCommand.AddGlobalOption(verboseOption); + + var quietOption = new Option( + ["--quiet", "-q"], + "Suppress all output (overrides --verbose if present)" + ); + rootCommand.AddGlobalOption(quietOption); + + var splitCommand = new Command("split", "Split .fwdata file (push Humpty off the wall)"); + var buildCommand = new Command("build", "Rebuild .fwdata file (put Humpty together again)"); + + rootCommand.Add(splitCommand); + rootCommand.Add(buildCommand); + + var filename = new Argument( + "file", + "Name of .fwdata file to create or split, or directory to create/split it in" + ); + splitCommand.Add(filename); + buildCommand.Add(filename); + + var hgRevOption = new Option( + ["--rev", "-r"], + "Revision to check out (default \"tip\")" + ); + hgRevOption.SetDefaultValue("tip"); + buildCommand.AddGlobalOption(hgRevOption); + + var timeoutOption = new Option( + ["--timeout", "-t"], + "Timeout in seconds for Hg commands (default 600)" + ); + timeoutOption.SetDefaultValue(600); + buildCommand.AddGlobalOption(timeoutOption); + + var cleanupOption = new Option( + ["--cleanup", "-c"], + "Clean repository after creating .fwdata file (CAUTION: deletes every other file except .fwdata)" + ); + buildCommand.Add(cleanupOption); + + buildCommand.SetHandler(BuildFwData, filename, verboseOption, quietOption, hgRevOption, timeoutOption, cleanupOption); + + var cleanupOptionForSplit = new Option( + ["--cleanup", "-c"], + "Delete .fwdata file after splitting" + ); + splitCommand.Add(cleanupOptionForSplit); + + splitCommand.SetHandler(SplitFwData, filename, verboseOption, quietOption, cleanupOptionForSplit); + + return await rootCommand.InvokeAsync(args); + } + + static FileInfo? MaybeLocateFwDataFile(string input) + { + if (Directory.Exists(input)) { + var dirInfo = new DirectoryInfo(input); + var fname = dirInfo.Name + ".fwdata"; + return new FileInfo(Path.Join(input, fname)); + } else if (File.Exists(input)) { + return new FileInfo(input); + } else if (File.Exists(input + ".fwdata")) { + return new FileInfo(input + ".fwdata"); + } else { + return null; + } + } + + static FileInfo LocateFwDataFile(string input) + { + var result = MaybeLocateFwDataFile(input); + if (result != null) return result; + if (input.EndsWith(".fwdata")) return new FileInfo(input); + return new FileInfo(input + ".fwdata"); + } + + static Task SplitFwData(string filename, bool verbose, bool quiet, bool cleanup) + { + IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); + progress.ShowVerbose = verbose; + var file = MaybeLocateFwDataFile(filename); + if (file == null || !file.Exists) { + progress.WriteError("Could not find {0}", filename); + return Task.FromResult(1); + } + string name = file.FullName; + progress.WriteVerbose("Splitting {0} ...", name); + LfMergeBridge.LfMergeBridge.DisassembleFwdataFile(progress, writeVerbose: true, name); + progress.WriteMessage("Finished splitting {0}", name); + if (cleanup) + { + progress.WriteVerbose("Cleaning up..."); + var fwdataFile = new FileInfo(name); + if (fwdataFile.Exists) { + fwdataFile.Delete(); + progress.WriteVerbose("Deleted {0}", fwdataFile.FullName); + } else { + progress.WriteVerbose("File not found, so not deleting: {0}", fwdataFile.FullName); + } + } + return Task.FromResult(0); + } + + static Task BuildFwData(string filename, bool verbose, bool quiet, string rev, int timeout, bool cleanup) + { + IProgress progress = quiet ? new NullProgress() : new ConsoleProgress(); + progress.ShowVerbose = verbose; + var file = LocateFwDataFile(filename); + if (file.Exists) { + progress.WriteWarning("File {0} already exists and will be overwritten", file.FullName); + } + var dir = file.Directory; + if (dir == null || !dir.Exists) { + progress.WriteError("Could not find directory {0}. MkFwData needs a Mercurial repo to work with.", dir?.FullName ?? "(null)"); + return Task.FromResult(1); + } + string name = file.FullName; + progress.WriteMessage("Checking out {0}", rev); + var result = HgRunner.Run($"hg checkout {rev}", dir.FullName, timeout, progress); + if (result.ExitCode != 0) + { + progress.WriteMessage("Could not find Mercurial repo in directory {0}. MkFwData needs a Mercurial repo to work with.", dir.FullName ?? "(null)"); + return Task.FromResult(result.ExitCode); + } + progress.WriteVerbose("Creating {0} ...", name); + LfMergeBridge.LfMergeBridge.ReassembleFwdataFile(progress, writeVerbose: true, name); + progress.WriteMessage("Created {0}", name); + if (cleanup) + { + progress.WriteVerbose("Cleaning up..."); + HgRunner.Run($"hg checkout null", dir.FullName, timeout, progress); + HgRunner.Run($"hg purge --no-confirm --exclude *.fwdata --exclude hgRunner.log", dir.FullName, timeout, progress); + } + return Task.FromResult(0); + } }