From 2c95104ee980551de3332ef5e442eaf63d99dce9 Mon Sep 17 00:00:00 2001 From: Taka Date: Fri, 28 Jan 2022 18:37:21 +1100 Subject: [PATCH] Use Spectre to parse command-line arguments. --- cli/Program.fs | 102 ++++++++++++++++++++-------------------- cli/cli.fsproj | 4 -- git-guts/GitGuts.fs | 5 ++ git-guts/tests/Utils.fs | 5 -- 4 files changed, 57 insertions(+), 59 deletions(-) diff --git a/cli/Program.fs b/cli/Program.fs index 4b90ef9..09ea438 100644 --- a/cli/Program.fs +++ b/cli/Program.fs @@ -1,42 +1,56 @@ open System open System.IO -open Argu +open Spectre.Console +open Spectre.Console.Cli open git_guts // -------------------------------------------------------------------- -type DumpPackFileArgs = - | [] Pack_Filename of packFilename:string - interface IArgParserTemplate with - member this.Usage = - match this with - | Pack_Filename _ -> "Pack file to dump." +let _getPackFilename packFilename repoDir = + if packFilename <> "" then + packFilename + else + // auto-detect pack files + let fnames = findRepoPacks repoDir + match fnames.Length with + | 0 -> failwith "No pack file was specified." + | 1 -> fnames.[0] + | _ -> failwith "Multiple pack files were found." + +// -------------------------------------------------------------------- -type CliArguments = - | [] Repo of path:string - | [] Dump_PackFile of ParseResults - interface IArgParserTemplate with - member this.Usage = - match this with - | Repo _ -> "specify the git repo directory." - | Dump_PackFile _ -> "dump a pack file." +type AppSettings() = + inherit CommandSettings() + [" )>] + member val RepoDir = "." with get, set + override this.Validate() = + this.RepoDir <- Path.GetFullPath( this.RepoDir ) + if not ( Directory.Exists this.RepoDir ) then + ValidationResult.Error( "Can't find git repo directory." ) + else + ValidationResult.Success() -type CliExiter() = - interface IExiter with - member __.Name = "CliExiter" - member __.Exit( msg, code ) = - if code = ErrorCode.HelpText then - // show the help text - printfn "%s" msg - exit 0 - else - // show the error message (sans help text) - let pos = msg.IndexOf "USAGE:" - let msg2 = msg.Substring( 0, pos-1 ) - printfn "%s" msg2 - printfn "Use --help to get help." - exit 1 +// FUDGE! We need this for the settings in AppSettings to be recognized :-/ +type AppCommand() = + inherit Command() + override this.Execute( ctx, settings ) = + failwith "No command was specified." + 0 + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +type DumpPackFileSettings() = + inherit AppSettings() + [" )>] + member val PackFilename = "" with get, set + +type DumpPackFileCommand() = + inherit Command() + override this.Execute( ctx, settings ) = + let fname = _getPackFilename settings.PackFilename settings.RepoDir + dumpPackFile fname + 0 // -------------------------------------------------------------------- @@ -50,23 +64,11 @@ let main argv = disableSpectreCapabilities // parse the command-line arguments - let programName = System.AppDomain.CurrentDomain.FriendlyName - let parser = ArgumentParser.Create( programName=programName, helpTextMessage="Examine the guts of a git repo.", errorHandler=CliExiter() ) - let parsedArgs = parser.Parse argv - let repoDir = Path.GetFullPath( parsedArgs.GetResult( Repo, defaultValue="." ) ) - if not ( Directory.Exists repoDir ) then - failwith "Can't find git repo directory." - - // perform the requested action - if parsedArgs.Contains Dump_PackFile then - // dump a pack file - let args = parsedArgs.GetResult Dump_PackFile - if not ( args.Contains Pack_Filename ) then - failwith "No pack file was specified." // nb: because [] doesn't seem to work :-/ - let fname = args.GetResult Pack_Filename - dumpPackFile fname - else - // no action was specified - print help - printfn "%s" ( parser.PrintUsage() ) - - 0 + let app = CommandApp() + app.Configure( fun cfg -> + cfg.SetApplicationName( System.AppDomain.CurrentDomain.FriendlyName ) |> ignore + cfg.AddCommand( "dump-packfile" ).WithDescription( + "Dump a pack file." + ) |> ignore + ) + app.Run( argv ) diff --git a/cli/cli.fsproj b/cli/cli.fsproj index 619f69d..4b2273e 100644 --- a/cli/cli.fsproj +++ b/cli/cli.fsproj @@ -10,10 +10,6 @@ - - - - diff --git a/git-guts/GitGuts.fs b/git-guts/GitGuts.fs index a6b39d5..96378be 100644 --- a/git-guts/GitGuts.fs +++ b/git-guts/GitGuts.fs @@ -69,3 +69,8 @@ module GitGuts = let buf = Array.zeroCreate 4 inp.Read( buf, 0, 4 ) |> ignore ( int(buf.[0]) <<< 24 ) ||| ( int(buf.[1]) <<< 16 ) ||| ( int(buf.[2]) <<< 8 ) ||| int(buf.[3]) + + let findRepoPacks repoDir = + // find pack files in the git repo + let dname = Path.Combine( repoDir, ".git/objects/pack" ) + Directory.GetFiles( dname, "*.pack" ) diff --git a/git-guts/tests/Utils.fs b/git-guts/tests/Utils.fs index 651eff6..b6e9b36 100644 --- a/git-guts/tests/Utils.fs +++ b/git-guts/tests/Utils.fs @@ -104,8 +104,3 @@ module Utils = let runGitGc repoDir = // run git garbage collection runGit repoDir "gc" [] |> ignore - - let findRepoPacks repoDir = - // find pack files in the git repo - let dname = Path.Combine( repoDir, ".git/objects/pack" ) - Directory.GetFiles( dname, "*.pack" )