diff --git a/docs/content/commands/pack.md b/docs/content/commands/pack.md new file mode 100644 index 0000000000..6f7a70fccb --- /dev/null +++ b/docs/content/commands/pack.md @@ -0,0 +1,56 @@ +## Creating NuGet-Packages + +Consider the following [`paket.dependencies` file][depfile] in your project's root: + + source https://nuget.org/api/v2 + + nuget Castle.Windsor ~> 3.2 + nuget NUnit + +And one of your projects having a [`paket.references` file][reffile] like this: + + Castle.Windsor + +Now, when you run `paket install`, your [`paket.lock` file][lockfile] would look like this: + + NUGET + remote: https://nuget.org/api/v2 + specs: + Castle.Core (3.3.3) + Castle.Windsor (3.3.0) + Castle.Core (>= 3.3.0) + NUnit (2.6.4) + +Now, when you are done programming and wish to create a NuGet-Package of your project, create a [`paket.template`][templatefile] file with `type project` and run: + + [lang=batch] + paket pack output nugets version 1.0.0 + +Or, you could run: + + [lang=batch] + paket pack output nugets version 1.0.0 lock-dependencies + +Depending on which command you issue, Paket creates different version requirements of the packages you depend on in the resulting `.nuspec` file of your package: + + + + + + + + + + + + + + +
DependencyDefaultWith locked dependencies
Castle.Windsor[3.2,4.0)[3.3.0]
+ +As you see here, the first command (without the `lock-dependencies` parameter) creates version requirements as specified in your [`paket.dependencies` file][depfile]. The second command takes the currently resolved versions from your [`paket.lock` file][lockfile] and "locks" them to these specific versions. + + [lockfile]: lock-file.html + [depfile]: dependencies-file.html + [reffile]: references-files.html + [templatefile]: template-files.html diff --git a/src/Paket.Core/PackageMetaData.fs b/src/Paket.Core/PackageMetaData.fs index d9f8abb5fe..692535ea32 100644 --- a/src/Paket.Core/PackageMetaData.fs +++ b/src/Paket.Core/PackageMetaData.fs @@ -137,7 +137,7 @@ let addFile (source : string) (target : string) (templateFile : TemplateFile) = | IncompleteTemplate -> failwith "You should only try and add dependencies to template files with complete metadata." -let findDependencies (dependencies : DependenciesFile) config (template : TemplateFile) (project : ProjectFile) (map : Map) = +let findDependencies (dependencies : DependenciesFile) config (template : TemplateFile) (project : ProjectFile) lockDependencies (map : Map) = let targetDir = match project.OutputType with | ProjectOutputType.Exe -> "tools/" @@ -183,7 +183,12 @@ let findDependencies (dependencies : DependenciesFile) config (template : Templa match templateFile with | CompleteTemplate(core, opt) -> match core.Version with - | Some v -> core.Id, VersionRequirement(Minimum(v), PreReleaseStatus.All) + | Some v -> + let versionConstraint = + if not lockDependencies + then Minimum v + else Specific v + core.Id, VersionRequirement(versionConstraint, PreReleaseStatus.All) | none ->failwithf "There was no version given for %s." templateFile.FileName | IncompleteTemplate -> failwithf "You cannot create a dependency on a template file (%s) with incomplete metadata." templateFile.FileName) |> List.fold addDependency templateWithOutput @@ -215,17 +220,27 @@ let findDependencies (dependencies : DependenciesFile) config (template : Templa with | _ -> true) |> List.map (fun np -> + let getDependencyVersionRequirement package = + if not lockDependencies then + Map.tryFind package dependencies.DirectDependencies + |> function + | Some direct -> Some direct + | None -> + // If it's a transient dependency, try to + // find it in `paket.lock` and set min version + // to current locked version + lockFile.ResolvedPackages + |> Map.tryFind (NormalizedPackageName package) + |> Option.map (fun transient -> transient.Version) + |> Option.map (fun v -> VersionRequirement(Minimum v, PreReleaseStatus.All)) + else + Map.tryFind (NormalizedPackageName package) lockFile.ResolvedPackages + |> Option.map (fun resolvedPackage -> resolvedPackage.Version) + |> Option.map (fun version -> VersionRequirement(Specific version, PreReleaseStatus.All)) let dep = - match Map.tryFind np.Name dependencies.DirectDependencies with - | Some direct -> direct - // If it's a transient dependency set - // min version to current locked version - | None -> - let resolved = - lockFile.ResolvedPackages - |> Map.find (NormalizedPackageName np.Name) - - VersionRequirement(Minimum resolved.Version, PreReleaseStatus.All) + match getDependencyVersionRequirement np.Name with + | Some installed -> installed + | None -> failwithf "No package with id '%A' installed." np.Name np.Name.Id, dep) |> List.fold addDependency withDepsAndIncluded | None -> withDepsAndIncluded diff --git a/src/Paket.Core/PackageProcess.fs b/src/Paket.Core/PackageProcess.fs index bd9a7c9052..7c3f1b1ca3 100644 --- a/src/Paket.Core/PackageProcess.fs +++ b/src/Paket.Core/PackageProcess.fs @@ -10,9 +10,9 @@ open System.Collections.Generic open Paket.PackageMetaData open Chessie.ErrorHandling -let Pack(workingDir,dependencies : DependenciesFile, packageOutputPath, buildConfig, version, releaseNotes, templateFile) = - let buildConfig = defaultArg buildConfig "Release" - let packageOutputPath = if Path.IsPathRooted(packageOutputPath) then packageOutputPath else Path.Combine(workingDir,packageOutputPath) +let Pack(workingDir,dependencies : DependenciesFile, packageOutputPath, buildConfig, version, releaseNotes, templateFile, lockDependencies) = + let buildConfig = defaultArg buildConfig "Release" + let packageOutputPath = if Path.IsPathRooted(packageOutputPath) then packageOutputPath else Path.Combine(workingDir,packageOutputPath) Utils.createDir packageOutputPath |> returnOrFail let version = version |> Option.map SemVer.Parse @@ -98,7 +98,7 @@ let Pack(workingDir,dependencies : DependenciesFile, packageOutputPath, buildCon // add dependencies let allTemplates = projectTemplates - |> Map.map (fun _ (t, p) -> p,findDependencies dependencies buildConfig t p projectTemplates) + |> Map.map (fun _ (t, p) -> p,findDependencies dependencies buildConfig t p lockDependencies projectTemplates) |> Map.toList |> List.map (fun (_,(_,x)) -> x) |> List.append [for fileName in allTemplateFiles -> TemplateFile.Load(fileName,version)] diff --git a/src/Paket.Core/PublicAPI.fs b/src/Paket.Core/PublicAPI.fs index f90831f4ff..31c7416c47 100644 --- a/src/Paket.Core/PublicAPI.fs +++ b/src/Paket.Core/PublicAPI.fs @@ -371,10 +371,11 @@ type Dependencies(dependenciesFileName: string) = FindReferences.FindReferencesForPackage (PackageName package) |> this.Process // Packs all paket.template files. - member this.Pack(outputPath, ?buildConfig, ?version, ?releaseNotes, ?templateFile, ?workingDir) = + member this.Pack(outputPath, ?buildConfig, ?version, ?releaseNotes, ?templateFile, ?workingDir, ?lockDependencies) = let dependenciesFile = DependenciesFile.ReadFromFile dependenciesFileName let workingDir = defaultArg workingDir (dependenciesFile.FileName |> Path.GetDirectoryName) - PackageProcess.Pack(workingDir, dependenciesFile, outputPath, buildConfig, version, releaseNotes, templateFile) + let lockDependencies = defaultArg lockDependencies false + PackageProcess.Pack(workingDir, dependenciesFile, outputPath, buildConfig, version, releaseNotes, templateFile, lockDependencies) /// Pushes a nupkg file. static member Push(packageFileName, ?url, ?apiKey, (?endPoint: string), ?maxTrials) = diff --git a/src/Paket/Commands.fs b/src/Paket/Commands.fs index 5c5c7c4cda..4ef400b395 100644 --- a/src/Paket/Commands.fs +++ b/src/Paket/Commands.fs @@ -251,6 +251,7 @@ type PackArgs = | [] Version of string | [] TemplateFile of string | [] ReleaseNotes of string + | [] LockDependencies with interface IArgParserTemplate with member this.Usage = @@ -260,6 +261,7 @@ with | Version(_) -> "Specify version of the package." | TemplateFile(_) -> "Allows to specify a single template file." | ReleaseNotes(_) -> "Specify relase notes for the package." + | LockDependencies -> "Get the version requirements from paket.lock instead of paket.dependencies." type PushArgs = | [][] Url of string diff --git a/src/Paket/Program.fs b/src/Paket/Program.fs index 08278c6bf7..92513ca8a0 100644 --- a/src/Paket/Program.fs +++ b/src/Paket/Program.fs @@ -180,7 +180,8 @@ let pack (results : ArgParseResults<_>) = ?version = results.TryGetResult <@ PackArgs.Version @>, ?releaseNotes = results.TryGetResult <@ PackArgs.ReleaseNotes @>, ?templateFile = results.TryGetResult <@ PackArgs.TemplateFile @>, - workingDir = Environment.CurrentDirectory) + workingDir = Environment.CurrentDirectory, + lockDependencies = results.Contains <@ PackArgs.LockDependencies @>) let findPackages (results : ArgParseResults<_>) = let maxResults = defaultArg (results.TryGetResult <@ FindPackagesArgs.MaxResults @>) 10000