diff --git a/src/Paket.Bootstrapper/WindowsProcessArguments.cs b/src/Paket.Bootstrapper/WindowsProcessArguments.cs
index e1b9df7e51..3912aea55e 100644
--- a/src/Paket.Bootstrapper/WindowsProcessArguments.cs
+++ b/src/Paket.Bootstrapper/WindowsProcessArguments.cs
@@ -3,7 +3,7 @@
namespace Paket.Bootstrapper
{
- static class WindowsProcessArguments
+ public static class WindowsProcessArguments
{
static void AddBackslashes(StringBuilder builder, int backslashes, bool beforeQuote)
{
diff --git a/src/Paket.CmdLineHelpers/Paket.CmdLineHelpers.csproj b/src/Paket.CmdLineHelpers/Paket.CmdLineHelpers.csproj
new file mode 100644
index 0000000000..84184ed101
--- /dev/null
+++ b/src/Paket.CmdLineHelpers/Paket.CmdLineHelpers.csproj
@@ -0,0 +1,11 @@
+
+
+
+ netcoreapp2.1
+
+
+
+
+
+
+
diff --git a/src/Paket.CmdLineHelpers/paket.references b/src/Paket.CmdLineHelpers/paket.references
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/Paket/Paket.fsproj b/src/Paket/Paket.fsproj
index 56ac8eb56a..88d0d0dcaf 100644
--- a/src/Paket/Paket.fsproj
+++ b/src/Paket/Paket.fsproj
@@ -1,7 +1,8 @@
Exe
- net461;netcoreapp2.1
+ netcoreapp2.1;net461
+ 5.239.0-beta-0001
false
Paket
paket
@@ -11,10 +12,14 @@
https://raw.githubusercontent.com/fsprojects/Paket/master/docs/files/img/logo.png
nuget;bundler;F#
+
+ PAKET_GLOBAL_LOCAL;$(DefineConstants)
+
netcoreapp2.1
+ PAKET_GLOBAL_LOCAL;$(DefineConstants)
@@ -25,14 +30,38 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Paket/Program.fs b/src/Paket/Program.fs
index 56d142682a..fcb0ef69e1 100644
--- a/src/Paket/Program.fs
+++ b/src/Paket/Program.fs
@@ -37,10 +37,11 @@ let processWithValidationEx printUsage silent validateF commandF result =
traceError (" " + String.Join(" ",Environment.GetCommandLineArgs()))
printUsage result
- Environment.ExitCode <- 1
+ 1
else
try
commandF result
+ 0
finally
sw.Stop()
if not silent then
@@ -866,6 +867,97 @@ let handleCommand silent command =
| Version
| Log_File _ -> failwithf "internal error: this code should never be reached."
+#if PAKET_GLOBAL_LOCAL
+
+(*
+#load @"..\Paket.Core\Common\Domain.fs"
+#load @"..\Paket.Core\Common\Logging.fs"
+#load @"..\Paket.Core\Common\Constants.fs"
+open System
+open System.IO
+open Paket
+*)
+
+let rec findRootInHierarchyFrom (dir: DirectoryInfo) =
+ if not (dir.Exists) then
+ None
+ else
+ let dotPaketDir =
+ Path.Combine(dir.FullName, Constants.PaketFolderName)
+ |> DirectoryInfo
+ if dotPaketDir.Exists then
+ Some dir
+ else
+ match dir.Parent with
+ | null -> None
+ | root -> findRootInHierarchyFrom root
+
+let findRootInHierarchy () =
+ (Directory.GetCurrentDirectory() |> DirectoryInfo)
+ |> findRootInHierarchyFrom
+
+let runIt exeName exeArgs =
+ use p = new Process()
+
+ // let argString : string = Paket.Bootstrapper.WindowsProcessArguments.ToString(exeArgs)
+ // let psi = ProcessStartInfo(FileName = exeName, Arguments = argString, UseShellExecute = false)
+ // printfn "Running: %s %A" exeName (psi.Arguments)
+
+ let psi = ProcessStartInfo(FileName = exeName, Arguments = "", UseShellExecute = false)
+ for arg in exeArgs do
+ psi.ArgumentList.Add(arg)
+ printfn "Running: %s %A" exeName (psi.ArgumentList |> Seq.toList)
+
+ p.StartInfo <- psi
+
+ p.Start() |> ignore
+ p.WaitForExit()
+ p.ExitCode
+
+
+[]
+type GlobalCommand =
+ // global options
+ | [] Silent
+ | [] Verbose
+ // subcommands
+ | [] Init of ParseResults
+with
+ interface IArgParserTemplate with
+ member this.Usage =
+ match this with
+ | Init _ -> "create an empty paket.dependencies file in the current working directory"
+ | Silent -> "suppress console output"
+ | Verbose -> "print detailed information to the console"
+
+let globalCommandParser = ArgumentParser.Create(programName = "paket", errorHandler = new ProcessExiter(), checkStructure = false)
+
+let dotnetToolManifestPath (dir: DirectoryInfo) =
+ Path.Combine(dir.FullName, ".config", "dotnet-tools.json")
+ |> FileInfo
+
+open System.Reflection
+
+let isToolLocal () =
+ let x = typeof.Assembly.Location
+ // printfn "%s" x
+
+ // local is like
+ // C:\Users\e0s01ao\.nuget\packages\paket\5.239.0-beta-0001\tools\netcoreapp2.1\any\paket.dll
+
+ // global is like
+ // C:\Users\e0s01ao\.dotnet\tools\.store\paket\5.239.0-beta-0001\paket\5.239.0-beta-0001\tools\netcoreapp2.1\any\paket.dll
+
+ let isToolGlobal = x.Contains(".store")
+
+ // printfn "tg %O" isToolGlobal
+
+ let isToolLocal = not isToolGlobal
+
+ isToolLocal
+
+#endif
+
let main() =
let waitDebuggerEnvVar = Environment.GetEnvironmentVariable ("PAKET_WAIT_DEBUGGER")
if waitDebuggerEnvVar = "1" then
@@ -932,12 +1024,91 @@ let main() =
| None -> null
handleCommand silent (results.GetSubCommand())
+ else
+ 0
with
| exn when not (exn :? System.NullReferenceException) ->
- Environment.ExitCode <- 1
traceErrorfn "Paket failed with"
if Environment.GetEnvironmentVariable "PAKET_DETAILED_ERRORS" = "true" then
printErrorExt true true true exn
else printError exn
+ 1
+
+#if PAKET_GLOBAL_LOCAL
+
+let handleGlobalCommand silent command =
+ match command with
+ | GlobalCommand.Init r -> processCommand silent (init) r
+ // global options; list here in order to maintain compiler warnings
+ // in case of new subcommands added
+ | GlobalCommand.Verbose
+ | GlobalCommand.Silent -> failwithf "internal error: this code should never be reached."
-main()
+let mainGlobal () =
+ let waitDebuggerEnvVar = Environment.GetEnvironmentVariable ("PAKET_WAIT_DEBUGGER")
+ if waitDebuggerEnvVar = "1" then
+ waitForDebugger()
+
+ Logging.verboseWarnings <- Environment.GetEnvironmentVariable "PAKET_DETAILED_WARNINGS" = "true"
+ use consoleTrace = Logging.event.Publish |> Observable.subscribe Logging.traceToConsole
+
+ // TODO ^--- no need to duplicate these, move in entrypoint
+
+ try
+ let parser = ArgumentParser.Create(programName = "paket",
+ helpTextMessage = sprintf "Paket version %s%sHelp was requested:" paketVersion Environment.NewLine,
+ errorHandler = new PaketExiter(),
+ checkStructure = false)
+
+ let results = parser.ParseCommandLine(raiseOnUsage = true)
+ let silent = results.Contains <@ GlobalCommand.Silent @>
+ tracePaketVersion silent
+
+ if results.Contains <@ GlobalCommand.Verbose @> then
+ Logging.verbose <- true
+ Logging.verboseWarnings <- true
+
+ handleGlobalCommand silent (results.GetSubCommand())
+
+ //TODO v---- no need to duplicate, move in entrypoint? or not
+ with
+ | exn when not (exn :? System.NullReferenceException) ->
+ traceErrorfn "Paket failed with"
+ if Environment.GetEnvironmentVariable "PAKET_DETAILED_ERRORS" = "true" then
+ printErrorExt true true true exn
+ else printError exn
+ 1
+
+#endif
+
+[]
+let theMain argv =
+#if PAKET_GLOBAL_LOCAL
+ let isToolLocal = isToolLocal ()
+
+ if isToolLocal then
+ main ()
+ else
+ let paketRoot = findRootInHierarchy ()
+ match paketRoot with
+ | None ->
+ // act as global tool (subset of commands)
+ mainGlobal ()
+ | Some dir ->
+ let manifestToolPath = dotnetToolManifestPath dir
+ if manifestToolPath.Exists then
+ // paket as local tool => `dotnet paket`
+
+ //TODO check if paket is installed in manifest! otherwise tell to user!
+
+ runIt "dotnet" [| yield "paket"; yield! argv |]
+ else
+ // old paket => `.paket/paket`
+ let paketExePath =
+ Path.Combine(dir.FullName, Constants.PaketFolderName, Constants.PaketFileName)
+ |> Path.GetFullPath
+ runIt paketExePath argv
+
+#else
+ main ()
+#endif