Skip to content

Commit

Permalink
Bang some things into a different shape
Browse files Browse the repository at this point in the history
  • Loading branch information
Numpsy committed Sep 22, 2024
1 parent 050e199 commit 0b68c7d
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 110 deletions.
174 changes: 70 additions & 104 deletions src/app/Fake.DotNet.Cli/DotNet.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@ namespace Fake.DotNet
/// .NET Core + CLI tools helpers
/// </summary>
[<RequireQualifiedAccess>]
#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

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

/// <summary>
/// .NET Core SDK default install directory (set to default SDK installer paths
Expand All @@ -39,61 +44,19 @@ module DotNet =
else
@"C:\Program Files\dotnet"

/// <summary>
/// Tries to get the DotNet SDK from the global.json, starts searching in the given directory.
/// Returns None if global.json is not found
/// </summary>
///
/// <param name="startDir">The directory to start search from</param>
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


/// <summary>
/// Gets the DotNet SDK from the global.json, starts searching in the given directory.
/// </summary>
let internal getSDKVersionFromGlobalJsonDir startDir : string =
tryGetSDKVersionFromGlobalJsonDir startDir
|> function
| Some version -> version
| None -> failwithf "global.json not found"

/// <summary>
/// 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
/// </summary>
let tryGetSDKVersionFromGlobalJson () : string option = tryGetSDKVersionFromGlobalJsonDir "."
let tryGetSDKVersionFromGlobalJson () : string option =
GlobalJson.tryGetSDKVersionFromGlobalJson ()

/// <summary>
/// Gets the DotNet SDK from the global.json. This file can exist in the working
/// directory or any of the parent directories
/// </summary>
let getSDKVersionFromGlobalJson () : string = getSDKVersionFromGlobalJsonDir "."
let getSDKVersionFromGlobalJson () : string =
GlobalJson.getSDKVersionFromGlobalJson ()

/// <summary>
/// Get dotnet cli executable path. Probes the provided path first, then as a fallback tries the system PATH
Expand Down Expand Up @@ -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<ConsoleMessage>()

Expand Down Expand Up @@ -806,6 +769,64 @@ module DotNet =
|> runRaw (FirstArgReplacement.ReplaceWith firstArgs) options
|> CreateProcess.map fst


/// <summary>
/// dotnet --version command options
/// </summary>
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 }


/// <summary>
/// dotnet info result
/// </summary>
type VersionResult = string

/// <summary>
/// Execute dotnet --version command
/// </summary>
///
/// <param name="setParams">set version command parameters</param>
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

/// <summary>
/// Setup the environment (<c>PATH</c> and <c>DOTNET_ROOT</c>) in such a way that started processes use the given
/// dotnet SDK installation. This is useful for example when using fable,
Expand Down Expand Up @@ -916,62 +937,6 @@ module DotNet =
__.MarkSuccess()
{ RID = rid.Value }


/// <summary>
/// dotnet --version command options
/// </summary>
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 }


/// <summary>
/// dotnet info result
/// </summary>
type VersionResult = string

/// <summary>
/// Execute dotnet --version command
/// </summary>
///
/// <param name="setParams">set version command parameters</param>
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

/// <summary>
/// Install .NET Core SDK if required
/// </summary>
Expand Down Expand Up @@ -2073,3 +2038,4 @@ module DotNet =
| false -> failwithf $"dotnet new --uninstall failed with code %i{result.ExitCode}"

__.MarkSuccess()
#endif
1 change: 1 addition & 0 deletions src/app/Fake.DotNet.Cli/Fake.DotNet.Cli.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="VisibleTo.fs" />
<Compile Include="GlobalJson.fs" />
<Compile Include="DotNet.fs" />
<Compile Include="CreateProcessExt.fs" />
</ItemGroup>
Expand Down
60 changes: 60 additions & 0 deletions src/app/Fake.DotNet.Cli/GlobalJson.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
module internal GlobalJson

open System.IO
open Newtonsoft.Json.Linq

/// <summary>
/// Tries to get the DotNet SDK from the global.json, starts searching in the given directory.
/// Returns None if global.json is not found
/// </summary>
///
/// <param name="startDir">The directory to start search from</param>
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


/// <summary>
/// Gets the DotNet SDK from the global.json, starts searching in the given directory.
/// </summary>
let internal getSDKVersionFromGlobalJsonDir startDir : string =
tryGetSDKVersionFromGlobalJsonDir startDir
|> function
| Some version -> version
| None -> failwithf "global.json not found"

/// <summary>
/// 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
/// </summary>
let tryGetSDKVersionFromGlobalJson () : string option = tryGetSDKVersionFromGlobalJsonDir "."

/// <summary>
/// Gets the DotNet SDK from the global.json. This file can exist in the working
/// directory or any of the parent directories
/// </summary>
let getSDKVersionFromGlobalJson () : string = getSDKVersionFromGlobalJsonDir "."
8 changes: 5 additions & 3 deletions src/app/Fake.Runtime/Fake.Runtime.fsproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<DefineConstants>$(DefineConstants);CORE_CLR;DOTNETCORE;EXPLICIT_DEPENDENCIES;NETSTANDARD;FAKE_RUNTIME</DefineConstants>
<DefineConstants>$(DefineConstants);CORE_CLR;DOTNETCORE;EXPLICIT_DEPENDENCIES;NETSTANDARD;FAKE_RUNTIME;FAKE_INTERNAL_DOTNET_CORE_CLI</DefineConstants>
<AssemblyName>Fake.Runtime</AssemblyName>
<NoWarn>FS3186</NoWarn>
</PropertyGroup>
Expand All @@ -13,6 +13,8 @@
<DefineConstants>$(DefineConstants);RELEASE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Fake.DotNet.Cli\GlobalJson.fs" Link="GlobalJson.fs" />
<Compile Include="..\Fake.DotNet.Cli\DotNet.fs" Link="DotNet.fs" />
<Compile Include="YaafFSharpScripting.fs" />
<Compile Include="ThisAssemblyInfo.fs" />
<Compile Include="..\Fake.Core.Process\CmdLineParsing.fs" />
Expand All @@ -36,7 +38,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Fake.Core.Context\Fake.Core.Context.fsproj" />
<ProjectReference Include="..\Fake.DotNet.Cli\Fake.DotNet.Cli.fsproj" />
<ProjectReference Include="..\Fake.Core.Process\Fake.Core.Process.fsproj" />
<ProjectReference Include="..\Fake.IO.FileSystem\Fake.IO.FileSystem.fsproj" />
<ProjectReference Include="..\Fake.Core.DependencyManager.Paket\Fake.Core.DependencyManager.Paket.fsproj" />
</ItemGroup>
Expand Down
6 changes: 3 additions & 3 deletions src/app/Fake.Runtime/SdkAssemblyResolver.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand All @@ -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
| [] ->
Expand Down

0 comments on commit 0b68c7d

Please sign in to comment.