From 0b68c7dd0f5bd052f4d7350be20c85546171d7a6 Mon Sep 17 00:00:00 2001 From: Richard Webb Date: Thu, 19 Sep 2024 20:00:49 +0100 Subject: [PATCH] Bang some things into a different shape --- src/app/Fake.DotNet.Cli/DotNet.fs | 174 +++++++----------- .../Fake.DotNet.Cli/Fake.DotNet.Cli.fsproj | 1 + src/app/Fake.DotNet.Cli/GlobalJson.fs | 60 ++++++ src/app/Fake.Runtime/Fake.Runtime.fsproj | 8 +- src/app/Fake.Runtime/SdkAssemblyResolver.fs | 6 +- 5 files changed, 139 insertions(+), 110 deletions(-) create mode 100644 src/app/Fake.DotNet.Cli/GlobalJson.fs diff --git a/src/app/Fake.DotNet.Cli/DotNet.fs b/src/app/Fake.DotNet.Cli/DotNet.fs index f9663feea5a..2efd40bf798 100644 --- a/src/app/Fake.DotNet.Cli/DotNet.fs +++ b/src/app/Fake.DotNet.Cli/DotNet.fs @@ -4,7 +4,11 @@ namespace Fake.DotNet /// .NET Core + CLI tools helpers /// [] +#if FAKE_INTERNAL_DOTNET_CORE_CLI +module InternalDotNet = +#else module DotNet = +#endif // NOTE: The #if can be removed once we have a working release with the "new" API // Currently we #load this file in build.fsx @@ -12,12 +16,13 @@ module DotNet = open Fake.Core open Fake.IO open Fake.IO.FileSystemOperators +#if !FAKE_INTERNAL_DOTNET_CORE_CLI open Fake.DotNet.NuGet +#endif open System open System.IO open System.Security.Cryptography open System.Text - open Newtonsoft.Json.Linq /// /// .NET Core SDK default install directory (set to default SDK installer paths @@ -39,61 +44,19 @@ module DotNet = else @"C:\Program Files\dotnet" - /// - /// Tries to get the DotNet SDK from the global.json, starts searching in the given directory. - /// Returns None if global.json is not found - /// - /// - /// The directory to start search from - let internal tryGetSDKVersionFromGlobalJsonDir startDir : string option = - let globalJsonPaths rootDir = - let rec loop (dir: DirectoryInfo) = - seq { - match dir.GetFiles "global.json" with - | [| json |] -> yield json - | _ -> () - - if not (isNull dir.Parent) then - yield! loop dir.Parent - } - - loop (DirectoryInfo rootDir) - - match Seq.tryHead (globalJsonPaths startDir) with - | None -> None - | Some globalJson -> - try - let content = File.ReadAllText globalJson.FullName - let json = JObject.Parse content - let sdk = json.Item("sdk") :?> JObject - - match sdk.Property("version") with - | null -> None - | version -> Some(version.Value.ToString()) - with exn -> - failwithf "Could not parse `sdk.version` from global.json at '%s': %s" globalJson.FullName exn.Message - - - /// - /// Gets the DotNet SDK from the global.json, starts searching in the given directory. - /// - let internal getSDKVersionFromGlobalJsonDir startDir : string = - tryGetSDKVersionFromGlobalJsonDir startDir - |> function - | Some version -> version - | None -> failwithf "global.json not found" - /// /// Tries the DotNet SDK from the global.json. This file can exist in the working /// directory or any of the parent directories Returns None if global.json is not found /// - let tryGetSDKVersionFromGlobalJson () : string option = tryGetSDKVersionFromGlobalJsonDir "." + let tryGetSDKVersionFromGlobalJson () : string option = + GlobalJson.tryGetSDKVersionFromGlobalJson () /// /// Gets the DotNet SDK from the global.json. This file can exist in the working /// directory or any of the parent directories /// - let getSDKVersionFromGlobalJson () : string = getSDKVersionFromGlobalJsonDir "." + let getSDKVersionFromGlobalJson () : string = + GlobalJson.getSDKVersionFromGlobalJson () /// /// Get dotnet cli executable path. Probes the provided path first, then as a fallback tries the system PATH @@ -695,7 +658,7 @@ module DotNet = | UsePreviousFile | ReplaceWith of string list - let internal runRaw (firstArg: FirstArgReplacement) options (c: CreateProcess<'a>) = + let internal runRaw (firstArg: FirstArgReplacement) (options: Options) (c: CreateProcess<'a>) = //let timeout = TimeSpan.MaxValue let results = System.Collections.Generic.List() @@ -806,6 +769,64 @@ module DotNet = |> runRaw (FirstArgReplacement.ReplaceWith firstArgs) options |> CreateProcess.map fst + + /// + /// dotnet --version command options + /// + type VersionOptions = + { + /// Common tool options + Common: Options + } + + /// Parameter default values. + static member Create() = + { Common = Options.Create().WithRedirectOutput true } + + /// Gets the current environment + member x.Environment = x.Common.Environment + + /// Changes the "Common" properties according to the given function + member inline x.WithCommon f = { x with Common = f x.Common } + + /// Sets the current environment variables. + member x.WithEnvironment map = + x.WithCommon(fun c -> { c with Environment = map }) + + /// Sets a value indicating whether the output for the given process is redirected. + member x.WithRedirectOutput shouldRedirect = + { x with Common = x.Common.WithRedirectOutput shouldRedirect } + + + /// + /// dotnet info result + /// + type VersionResult = string + + /// + /// Execute dotnet --version command + /// + /// + /// set version command parameters + let getVersion setParams = + use __ = Trace.traceTask "DotNet:version" "running dotnet --version" + let param = VersionOptions.Create() |> setParams + let args = "--version" + let result = exec (fun _ -> param.Common) "" args + + if not result.OK then + failwithf "dotnet --version failed with code %i" result.ExitCode + + let version = result.Messages |> String.separated "\n" |> String.trim + + if String.isNullOrWhiteSpace version then + failwithf "could not read version from output: \n%s" (String.Join("\n", result.Messages)) + + __.MarkSuccess() + version + +#if !FAKE_INTERNAL_DOTNET_CORE_CLI + /// /// Setup the environment (PATH and DOTNET_ROOT) in such a way that started processes use the given /// dotnet SDK installation. This is useful for example when using fable, @@ -916,62 +937,6 @@ module DotNet = __.MarkSuccess() { RID = rid.Value } - - /// - /// dotnet --version command options - /// - type VersionOptions = - { - /// Common tool options - Common: Options - } - - /// Parameter default values. - static member Create() = - { Common = Options.Create().WithRedirectOutput true } - - /// Gets the current environment - member x.Environment = x.Common.Environment - - /// Changes the "Common" properties according to the given function - member inline x.WithCommon f = { x with Common = f x.Common } - - /// Sets the current environment variables. - member x.WithEnvironment map = - x.WithCommon(fun c -> { c with Environment = map }) - - /// Sets a value indicating whether the output for the given process is redirected. - member x.WithRedirectOutput shouldRedirect = - { x with Common = x.Common.WithRedirectOutput shouldRedirect } - - - /// - /// dotnet info result - /// - type VersionResult = string - - /// - /// Execute dotnet --version command - /// - /// - /// set version command parameters - let getVersion setParams = - use __ = Trace.traceTask "DotNet:version" "running dotnet --version" - let param = VersionOptions.Create() |> setParams - let args = "--version" - let result = exec (fun _ -> param.Common) "" args - - if not result.OK then - failwithf "dotnet --version failed with code %i" result.ExitCode - - let version = result.Messages |> String.separated "\n" |> String.trim - - if String.isNullOrWhiteSpace version then - failwithf "could not read version from output: \n%s" (String.Join("\n", result.Messages)) - - __.MarkSuccess() - version - /// /// Install .NET Core SDK if required /// @@ -2073,3 +2038,4 @@ module DotNet = | false -> failwithf $"dotnet new --uninstall failed with code %i{result.ExitCode}" __.MarkSuccess() +#endif diff --git a/src/app/Fake.DotNet.Cli/Fake.DotNet.Cli.fsproj b/src/app/Fake.DotNet.Cli/Fake.DotNet.Cli.fsproj index cef17509075..e199c022af4 100644 --- a/src/app/Fake.DotNet.Cli/Fake.DotNet.Cli.fsproj +++ b/src/app/Fake.DotNet.Cli/Fake.DotNet.Cli.fsproj @@ -17,6 +17,7 @@ + diff --git a/src/app/Fake.DotNet.Cli/GlobalJson.fs b/src/app/Fake.DotNet.Cli/GlobalJson.fs new file mode 100644 index 00000000000..bc4da3939c3 --- /dev/null +++ b/src/app/Fake.DotNet.Cli/GlobalJson.fs @@ -0,0 +1,60 @@ +module internal GlobalJson + +open System.IO +open Newtonsoft.Json.Linq + +/// +/// Tries to get the DotNet SDK from the global.json, starts searching in the given directory. +/// Returns None if global.json is not found +/// +/// +/// The directory to start search from +let internal tryGetSDKVersionFromGlobalJsonDir startDir : string option = + let globalJsonPaths rootDir = + let rec loop (dir: DirectoryInfo) = + seq { + match dir.GetFiles "global.json" with + | [| json |] -> yield json + | _ -> () + + if not (isNull dir.Parent) then + yield! loop dir.Parent + } + + loop (DirectoryInfo rootDir) + + match Seq.tryHead (globalJsonPaths startDir) with + | None -> None + | Some globalJson -> + try + let content = File.ReadAllText globalJson.FullName + let json = JObject.Parse content + let sdk = json.Item("sdk") :?> JObject + + match sdk.Property("version") with + | null -> None + | version -> Some(version.Value.ToString()) + with exn -> + failwithf "Could not parse `sdk.version` from global.json at '%s': %s" globalJson.FullName exn.Message + + +/// +/// Gets the DotNet SDK from the global.json, starts searching in the given directory. +/// +let internal getSDKVersionFromGlobalJsonDir startDir : string = + tryGetSDKVersionFromGlobalJsonDir startDir + |> function + | Some version -> version + | None -> failwithf "global.json not found" + +/// +/// Tries the DotNet SDK from the global.json. This file can exist in the working +/// directory or any of the parent directories Returns None if global.json is not found +/// +let tryGetSDKVersionFromGlobalJson () : string option = tryGetSDKVersionFromGlobalJsonDir "." + +/// +/// Gets the DotNet SDK from the global.json. This file can exist in the working +/// directory or any of the parent directories +/// +let getSDKVersionFromGlobalJson () : string = getSDKVersionFromGlobalJsonDir "." diff --git a/src/app/Fake.Runtime/Fake.Runtime.fsproj b/src/app/Fake.Runtime/Fake.Runtime.fsproj index 4eb4f35e8cf..2feddb37c5a 100644 --- a/src/app/Fake.Runtime/Fake.Runtime.fsproj +++ b/src/app/Fake.Runtime/Fake.Runtime.fsproj @@ -1,7 +1,7 @@ - + net6.0 - $(DefineConstants);CORE_CLR;DOTNETCORE;EXPLICIT_DEPENDENCIES;NETSTANDARD;FAKE_RUNTIME + $(DefineConstants);CORE_CLR;DOTNETCORE;EXPLICIT_DEPENDENCIES;NETSTANDARD;FAKE_RUNTIME;FAKE_INTERNAL_DOTNET_CORE_CLI Fake.Runtime FS3186 @@ -13,6 +13,8 @@ $(DefineConstants);RELEASE + + @@ -36,7 +38,7 @@ - + diff --git a/src/app/Fake.Runtime/SdkAssemblyResolver.fs b/src/app/Fake.Runtime/SdkAssemblyResolver.fs index 18fb4dad9d5..cd2dcf31b72 100644 --- a/src/app/Fake.Runtime/SdkAssemblyResolver.fs +++ b/src/app/Fake.Runtime/SdkAssemblyResolver.fs @@ -66,7 +66,7 @@ type SdkAssemblyResolver(logLevel: Trace.VerboseLevel) = member this.SdkVersion = this.SdkVersions |> Seq.head member this.PaketFrameworkIdentifier = this.PaketFrameworkIdentifiers |> Seq.head - member this.SdkVersionFromGlobalJson = DotNet.tryGetSDKVersionFromGlobalJson () + member this.SdkVersionFromGlobalJson = GlobalJson.tryGetSDKVersionFromGlobalJson () member this.IsSdkVersionFromGlobalJsonSameAsSdkVersion() = match this.SdkVersionFromGlobalJson with @@ -217,7 +217,7 @@ type SdkAssemblyResolver(logLevel: Trace.VerboseLevel) = this.GetProductReleasesForSdk version |> List.tryHead member this.ResolveSdkRuntimeVersions() = - let versionOptions (options: DotNet.VersionOptions) = + let versionOptions (options: InternalDotNet.VersionOptions) = // If a custom CLI path is provided, configure the version command // to use that path. This really only accomodates a test scenarios // in which FAKE_SDK_RESOLVER_CUSTOM_DOTNET_PATH is set. @@ -226,7 +226,7 @@ type SdkAssemblyResolver(logLevel: Trace.VerboseLevel) = options.WithCommon(fun common -> { common with DotNetCliPath = root this.DotNetBinaryName }) | None -> options - let sdkVersion = DotNet.getVersion versionOptions |> ReleaseVersion + let sdkVersion = InternalDotNet.getVersion versionOptions |> ReleaseVersion match this.GetProductReleasesForSdk sdkVersion with | [] ->