diff --git a/src/Paket.Core/Domain.fs b/src/Paket.Core/Domain.fs index c51cee6546..18e0e69f31 100644 --- a/src/Paket.Core/Domain.fs +++ b/src/Paket.Core/Domain.fs @@ -55,6 +55,13 @@ type DomainMessage = | DependencyNotFoundInLockFile of PackageName | ReferenceNotFoundInLockFile of string * PackageName + | DownloadError of string + | ReleasesJsonParseError + + | DirectoryCreateError of string + | FileDeleteError of string + | FileSaveError of string + override this.ToString() = match this with | DirectoryDoesntExist(di) -> @@ -88,3 +95,15 @@ type DomainMessage = sprintf "Dependency %s from %s not found in lock file." name Constants.DependenciesFileName | ReferenceNotFoundInLockFile(path, PackageName name) -> sprintf "Reference %s from %s not found in lock file." name path + + | DownloadError url -> + sprintf "Error occured while downloading from %s." url + | ReleasesJsonParseError -> + "Unable to parse Json from GitHub releases API." + + | DirectoryCreateError path -> + sprintf "Unable to create directory %s." path + | FileDeleteError path -> + sprintf "Unable to delete file %s." path + | FileSaveError path -> + sprintf "Unable to save file %s." path \ No newline at end of file diff --git a/src/Paket.Core/Environment.fs b/src/Paket.Core/Environment.fs index 65097a1a1c..26f27f4f56 100644 --- a/src/Paket.Core/Environment.fs +++ b/src/Paket.Core/Environment.fs @@ -80,3 +80,15 @@ module PaketEnv = let ensureLockFileExists environment = environment.LockFile |> failIfNone (LockFileNotFound environment.RootDirectory) + + let init (directory : DirectoryInfo) = + match locatePaketRootDirectory directory with + | Some rootDirectory -> + Logging.tracefn "Paket is already initialized in %s" rootDirectory.FullName + succeed () + | None -> + let dependenciesFile = + DependenciesFile( + Path.Combine(directory.FullName, Constants.DependenciesFileName), + InstallOptions.Default, [], [], []) + dependenciesFile.ToString() |> saveFile dependenciesFile.FileName \ No newline at end of file diff --git a/src/Paket.Core/NugetConvert.fs b/src/Paket.Core/NugetConvert.fs index 5da51d49cc..83857b76db 100644 --- a/src/Paket.Core/NugetConvert.fs +++ b/src/Paket.Core/NugetConvert.fs @@ -349,9 +349,8 @@ let replaceNugetWithPaket initAutoRestore installAfter result = result.NugetEnv.NugetConfig.PackageRestoreAutomatic && result.NugetEnv.NugetConfig.PackageRestoreEnabled - let dependenciesFileName = result.PaketEnv.DependenciesFile.FileName if initAutoRestore && (autoVSPackageRestore || result.NugetEnv.NugetTargets.IsSome) then - VSIntegration.InitAutoRestore dependenciesFileName + VSIntegration.InitAutoRestore result.PaketEnv |> returnOrFail if installAfter then - UpdateProcess.Update(dependenciesFileName,true,true,true) \ No newline at end of file + UpdateProcess.Update(result.PaketEnv.DependenciesFile.FileName,true,true,true) \ No newline at end of file diff --git a/src/Paket.Core/PublicAPI.fs b/src/Paket.Core/PublicAPI.fs index 9e77f928c7..e2eae4294c 100644 --- a/src/Paket.Core/PublicAPI.fs +++ b/src/Paket.Core/PublicAPI.fs @@ -43,19 +43,18 @@ type Dependencies(dependenciesFileName: string) = let dependenciesFileName = findInPath(DirectoryInfo path,true) tracefn "found: %s" dependenciesFileName Dependencies(dependenciesFileName) - - /// Tries to create a paket.dependencies file in the given folder. - static member Create(): Dependencies = Dependencies.Create(Environment.CurrentDirectory) - - /// Tries to create a paket.dependencies file in the given folder. - static member Create(path: string): Dependencies = - let dependenciesFileName = Path.Combine(path,Constants.DependenciesFileName) - if File.Exists dependenciesFileName then - Logging.tracefn "%s already exists" dependenciesFileName - else - DependenciesFile(dependenciesFileName, InstallOptions.Default, [], [], []).Save() - Dependencies(dependenciesFileName) - + + /// Initialize paket.dependencies file in current directory + static member Init() = + let currentDirectory = DirectoryInfo(Environment.CurrentDirectory) + + Utils.RunInLockedAccessMode( + currentDirectory.FullName, + fun () -> + PaketEnv.init currentDirectory + |> returnOrFail + ) + /// Converts the solution from NuGet to Paket. static member ConvertFromNuget(force: bool,installAfter: bool,initAutoRestore: bool,credsMigrationMode: string option) : unit = let currentDirectory = DirectoryInfo(Environment.CurrentDirectory) @@ -163,7 +162,7 @@ type Dependencies(dependenciesFileName: string) = member this.InitAutoRestore(): unit = Utils.RunInLockedAccessMode( this.RootPath, - fun () -> VSIntegration.InitAutoRestore(dependenciesFileName)) + fun () -> VSIntegration.InitAutoRestore |> this.Process) /// Returns the installed version of the given package. member this.GetInstalledVersion(packageName: string): string option = diff --git a/src/Paket.Core/Utils.fs b/src/Paket.Core/Utils.fs index 19270104ff..997241a5a8 100644 --- a/src/Paket.Core/Utils.fs +++ b/src/Paket.Core/Utils.fs @@ -8,6 +8,8 @@ open System.Net open System.Xml open System.Text open Paket.Logging +open Paket.Rop +open Paket.Domain type Auth = { Username : string @@ -28,9 +30,13 @@ let TimeSpanToReadableString(span:TimeSpan) = if String.IsNullOrEmpty(formatted) then "0 seconds" else formatted /// Creates a directory if it does not exist. -let CreateDir path = - let dir = DirectoryInfo path - if not dir.Exists then dir.Create() +let createDir path = + try + let dir = DirectoryInfo path + if not dir.Exists then dir.Create() + succeed () + with _ -> + DirectoryCreateError path |> fail /// Cleans a directory by deleting it and recreating it. let CleanDir path = @@ -40,7 +46,7 @@ let CleanDir path = di.Delete(true) with | exn -> failwithf "Error during deletion of %s%s - %s" di.FullName Environment.NewLine exn.Message - CreateDir path + createDir path |> returnOrFail // set writeable File.SetAttributes(path, FileAttributes.Normal) @@ -245,4 +251,24 @@ module String = let inline orElse v = function | Some x -> Some x - | None -> v \ No newline at end of file + | None -> v + +let downloadStringSync (url : string) (client : System.Net.WebClient) = + try + client.DownloadString url |> succeed + with _ -> + DownloadError url |> fail + +let downloadFileSync (url : string) (fileName : string) (client : System.Net.WebClient) = + tracefn "Downloading file from %s to %s" url fileName + try + client.DownloadFile(url, fileName) |> succeed + with _ -> + DownloadError url |> fail + +let saveFile (fileName : string) (contents : string) = + tracefn "Saving file %s" fileName + try + File.WriteAllText(fileName, contents) |> succeed + with _ -> + FileSaveError fileName |> fail \ No newline at end of file diff --git a/src/Paket.Core/VSIntegration.fs b/src/Paket.Core/VSIntegration.fs index 224393bd42..400d5a3a0d 100644 --- a/src/Paket.Core/VSIntegration.fs +++ b/src/Paket.Core/VSIntegration.fs @@ -3,39 +3,45 @@ open System.IO open Logging open System +open Rop +open Domain -let InitAutoRestore(dependenciesFileName) = - let root = - if dependenciesFileName = Constants.DependenciesFileName then - "." - else - Path.GetDirectoryName dependenciesFileName - CreateDir(Path.Combine(root,".paket")) +let private getLatestVersionFromJson (data : string) = + try + let start = data.IndexOf("tag_name") + 11 + let end' = data.IndexOf("\"", start) + (data.Substring(start, end' - start)) |> SemVer.Parse |> succeed + with _ -> + fail ReleasesJsonParseError + +let InitAutoRestore environment = + let exeDir = Path.Combine(environment.RootDirectory.FullName, ".paket") use client = createWebClient None - let releasesUrl = "https://api.github.com/repos/fsprojects/Paket/releases"; - let data = client.DownloadString(releasesUrl) - let start = data.IndexOf("tag_name") + 11 - let end' = data.IndexOf("\"", start) - let latestVersion = data.Substring(start, end' - start); - - for file in ["paket.targets"; "paket.bootstrapper.exe"] do - try - File.Delete(Path.Combine(root, ".paket", file)) - with _ -> traceErrorfn "Unable to delete %s" file - try - client.DownloadFile(sprintf "https://github.com/fsprojects/Paket/releases/download/%s/%s" latestVersion file, - Path.Combine(root, ".paket", file)) - tracefn "Downloaded %s" file - with _ -> traceErrorfn "Unable to download %s for version %s" file latestVersion - - let projectsUnderPaket = - ProjectFile.FindAllProjects root - |> Array.filter (fun project -> ProjectFile.FindReferencesFile(FileInfo(project.FileName)).IsSome) - - for project in projectsUnderPaket do - let relativePath = - createRelativePath project.FileName (Path.Combine(root, ".paket", "paket.targets")) - project.AddImportForPaketTargets(relativePath) - project.Save() \ No newline at end of file + let download version file = + rop { + do! createDir(exeDir) + let fileName = Path.Combine(exeDir, file) + let url = sprintf "https://github.com/fsprojects/Paket/releases/download/%s/%s" (string version) file + do! downloadFileSync url fileName client + } + + rop { + let releasesUrl = "https://api.github.com/repos/fsprojects/Paket/releases"; + let! data = client |> downloadStringSync releasesUrl + let! latestVersion = getLatestVersionFromJson data + + let! downloads = + ["paket.targets"; "paket.bootstrapper.exe"] + |> List.map (download latestVersion) + |> collect + + environment.Projects + |> List.map fst + |> List.iter (fun project -> + let relativePath = createRelativePath project.FileName (Path.Combine(exeDir, "paket.targets")) + project.AddImportForPaketTargets(relativePath) + project.Save() + ) + } \ No newline at end of file diff --git a/src/Paket/Program.fs b/src/Paket/Program.fs index d1a64cda7a..774a7f039a 100644 --- a/src/Paket/Program.fs +++ b/src/Paket/Program.fs @@ -155,7 +155,7 @@ try else match command with - | Command.Init -> Dependencies.Create() |> ignore + | Command.Init -> Dependencies.Init() | Command.Add -> let packageName = results.GetResult <@ CLIArguments.Nuget @> let version =