Paket 12 only ships as the paket .NET tool, which needs the .NET 10 runtime: paket.exe, paket.bootstrapper.exe and Mono are no longer supported. To upgrade, install Paket as a local tool (https://fsprojects.github.io/Paket/installation.html#Moving-from-paket-exe-and-the-bootstrapper). To keep paket.exe for now, remove the version line from paket.dependencies and run .paket/paket.bootstrapper.exe --self: you get the bootstrapper of Paket 11, which stays on the latest 11.x.
When the tool manifest declares paket, the restore during the builds and #r "paket:" in F# scripts run the local tool, before a Paket installed with --tool-path. Paket.Core targets net10.0 and drops its obsolete members, the command line no longer takes the syntax that Paket 5.5 replaced nor the generate-include-scripts and fix-nuspec commands, Paket no longer looks for projects in the folders whose name starts with a dot or that are links, and paket pack --release-notes-file reads the file with Fake.Core.ReleaseNotes 6.
This release also recognizes .NET 11, supports .slnx solutions, moves to the NuGet client libraries 7.9, writes paket.lock faster, and fixes many issues of git dependencies and of the restore. The next paket install or paket update may rewrite some framework restrictions of paket.lock, for the OS-specific frameworks of .NET 9 to 11 and in a shorter form.
- feat(BREAKING): Paket only ships as a .NET tool:
dotnet tool install paket.paket.exeandpaket.bootstrapper.exeare no longer built, and Paket no longer runs on Mono or the .NET Framework. See https://fsprojects.github.io/Paket/installation.html#Moving-from-paket-exe-and-the-bootstrapper - feat(BREAKING): The release and
tools/paket.exeof the Paket package carry apaket.exestub instead, so that bootstrappers older than 11.0 explain how to move on: it prints the steps and exits with code 1. To stay onpaket.exe, move to the bootstrapper of Paket 11, which stays on the latest 11.x: remove theversionline from paket.dependencies, then runpaket.bootstrapper.exe --self. - feat(BREAKING):
Paket.Restore.targetsandpaket.targetsno longer run the bootstrapper or runpaket.exethrough mono. They find Paket installed with--tool-path(in.paketor the root), as a local tool, or on thePATHlike a global tool. TheMonoPathandPaketBootStrapper*properties are gone; thePaketBootstrappingtarget is kept, empty, for the projects that depend on it. - fix(BREAKING): When the tool manifest declares paket,
Paket.Restore.targetsandpaket.targetsrun the local tool instead of a Paket installed with--tool-pathin.paketor the root, which can be an older Paket left by the move to the .NET tool, such as thepaket.exeor bootstrapper of Paket 11. They skip it with the warningPAKET0001, on every OS, whichNoWarncan turn off. To keep running it, setPaketExePathto its full path - fix(BREAKING): When a
.config/dotnet-tools.jsonordotnet-tools.jsonup from the script declares paket,#r "paket:"in F# scripts runs that local tool instead of a Paket installed with--tool-pathup from the script, which can be an older Paket such as thepaket.exeor bootstrapper of Paket 11, and shows a warning. When the local tool isn't restored, it asks to rundotnet tool restoreinstead of running that Paket. As dotnet, it no longer looks for a manifest above anisRootone - feat(BREAKING): Paket.Core targets net10.0 instead of netstandard2.0 and net461: the projects and scripts that reference it must target net10.0 or later, as the
paket.NET tool already needs the .NET 10 runtime. FSharp.DependencyManager.Paket stays on netstandard2.0 - #4317 - refactor(BREAKING): In Paket.Core,
Dependencies.DownloadLatestBootstrapperand thedownloadBootstrapperparameter ofDependencies.Initare removed, along with theReleasesmodule,Utils.isMonoRuntime,Utils.isMono,Utils.monoPath,Utils.fixArchive,ProcessHelper.monoArguments,ProcessHelper.appSettings,FrameworkDetection.resolveEnvironmentFramework(replaced bydefaultScriptFramework),Queries.resolveEnvironmentFrameworkForScriptGenerationand theBootstrapperFileName,PaketFileNameandGithubReleaseDownloadUrlconstants.ProcessHelper.tryFindPathandfindPathtake the;-separated paths instead of an app setting name. ThePAKET_PUSH_HTTPCLIENTvariable is gone:paket pushalways uses HttpClient. - refactor(BREAKING): The obsolete
InstallModel.CreateFromLibsandInstallModel.createFromLibs,InstallModel.GetLibReferencesandPlatformMatching.getFrameworkPathPenaltyof Paket.Core are removed: useInstallModel.CreateFromContentandcreateFromContent,GetLegacyReferencesorGetCompileReferences, andPlatformMatching.getPathPenalty. So is theFake.Globbingmodule that Paket.Core carried from FAKE 4: useFake.IO.Globbing.Globof the Fake.IO.FileSystem package. So areNuGetCache.NuGetConfig.writeNuGetConfigandConstants.NuGetConfigFile, unused since the end of the project.json support - refactor(BREAKING): The obsolete
Dependencies.ShowOutdatedandDependencies.FindOutdatedoverloads without theforceparameter,NuGet.GetLibFiles,NuGet.GetTargetsFiles,NuGet.GetAnalyzerFiles,InstallModel.GetReferenceFoldersandFrameworkDetection.Extractof Paket.Core are removed: use the overloads withforceset totrue,NuGet.GetContentwithNuGet.tryFindFolder,InstallModel.CompileLibFoldersandPlatformMatching.extractPlatforms, whosePlatformshold the framework. So is theDependencies.FixNuspecsoverload that takes the path of theobj/*.referencesfile of a project: use the one that takes theProjectFileand itsReferencesFile - refactor(BREAKING): The obsolete
paket generate-include-scriptsandpaket fix-nuspeccommands, and thereferences-fileoption ofpaket fix-nuspecs, are removed: usepaket generate-load-scripts, andpaket fix-nuspecs files <nuspec files> project-file <project file>asPaket.Restore.targetsdoes since Paket 5.92. The.paket/Paket.Restore.targetsof an older Paket is replaced at the nextpaket installor fullpaket restore - refactor(BREAKING): The paket command line no longer accepts the syntax that Paket 5.5 replaced, which it still took with a warning: the options without dashes, as in
paket add nuget Foo version 1.0,paket pack output bin buildconfig Debug templatefile paket.templateorpaket push file Foo.nupkg url https://example.org apikey KEY, and the old names--createnewbindingfiles,--creds-migrationsand--references-files. Writepaket add Foo --version 1.0,paket pack bin --build-config Debug --template paket.template,paket push Foo.nupkg --url https://example.org --api-key KEY,--create-new-binding-files,--migrate-credentialsand--references-file(once per file). The.paket/paket.targetsof Paket 5.97.0 and earlier passes--references-files: the nextpaket installor fullpaket restorereplaces it. The Ionide-Paket extension of Visual Studio Code, last updated in 2020, still passes this syntax to add, remove or update a package and to update a group - fix(BREAKING): Paket no longer looks for projects and
paket.templatefiles in the folders whose name starts with a dot, like.devenv, nor in the folders that are links, aspaket convert-from-nugetalready did for the solutions and NuGet files: the projects there are left out of install, restore, update, remove and pack. Until now only.gitand.fablewere skipped. A cyclic link, as in a Nix.devenvprofile, no longer makes the search run forever - #4421 - deps(BREAKING):
paket pack --release-notes-filereads the file with Fake.Core.ReleaseNotes 6, in the formats described in https://fake.build/reference/fake-core-releasenotes.html: the package version is the first word of the latest header that is a whole SemVer version, so## [1.2.3] - 2020-01-01and## v1.2.3 - 2020-01-01give2020-01-01; pass--versionfor such headers. Prerelease versions like1.2.3-beta.11.2are no longer cut, and build metadata (+sha.abc) is kept - fsprojects/FAKE#2686 - feat: The release carries the
paket.targetsandpaket.bootstrapper.exeof the latest Paket 11 release, for Paket 11.0.0 and earlier, which download them from the latest release onauto-restore on,convert-from-nugetandinit, and for the--selfof the bootstrappers older than 11.0 - feat:
paket auto-restore onwritespaket.targetsfrom Paket itself instead of downloading it from the latest GitHub release, so it works offline and matches the running Paket - feat:
paket install,paket restore, andupdate,addandremovewhen they install rewrite an existing.paket/paket.targetswith the one of the running Paket, unlessPAKET_SKIP_RESTORE_TARGETSistrue, so that a repository that turned auto-restore on with Paket 11 no longer keeps the one that runspaket.exethrough mono outside Windows and falls back to the bootstrapper. A restore with--project,--references-fileor--only-referenced, like the onepaket.targetsruns during a build, leaves it as it is. - feat:
#r "paket:"in F# scripts finds the Paket .NET tool: installed with--tool-path, as a local tool of the manifest, as a global tool, or restored in the NuGet packages folder - feat: Recognize the .NET 11 monikers:
net11.0,net11.0-windows...,net11.0-androidand the other OS-specific ones, andnetcoreapp11.0- #4439 - feat: Add support for
.slnxsolution files - #4443 - feat:
paket convert-from-nugetnow updates.slnxsolution files, as it does.slnones - #4443 - perf: Faster framework restrictions: writing the lock files of large repositories takes a quarter of the time and allocates less than 40% of the memory it did - #4317
- deps: Update the NuGet client libraries from 5.11 to 7.9, along with System.Net.Http.WinHttpHandler and System.Security.Cryptography.ProtectedData
- deps: Update Argu from 6.1.1 to 6.2.5, and System.Configuration.ConfigurationManager from 4.7 to 10.0, so the
pakettool no longer ships System.Drawing.Common 4.7 and its critical vulnerability (GHSA-rxg9-xrhp-64gj). The help ofpaket update,paket find-packagesandpaket generate-nuspecno longer shows their optional package ID, search text andoutputdirectory as required - fix: The conditions written in project files now list the OS-specific frameworks of .NET 9 to 11 (
net9.0-android,net10.0-ios,net11.0-macos...), which were left out in favour of their .NET 8 counterparts - fix: The OS-specific frameworks of .NET 9 to 11 fall back to the previous .NET version for the same OS, as the Windows ones do: a
net11.0-androidproject can use thenet10.0-androidassets and dependencies of a package - fix:
paket installno longer rewrites the framework restrictions of unchanged packages in paket.lock when it saves it for another reason, such as a removedgithubfile, in groups with aframework:line: these restrictions are written in a single, shorter form, without empty clauses like(&& (== net10.0) (== net461)). The restrictions of the dependencies are rewritten once at the nextpaket install, and those of the packages when their group is resolved again; they hold the same frameworks - fix: With MSBuild 15.8 or later,
paket.targetsskips the restore whenpaket-files/paket.restore.cachedsays that the last full restore, as bypaket installorpaket restoreof all the groups and projects, was of the currentpaket.lock, instead of restoring on every build of a project without the SDK. It still restores whilepaket.localexists, when thepackagesfolder is missing unlesspaket.lockhasstorage: nonefor all its groups, the main one included, and packages, and after it restored a project for anotherpaket.lock, for a missingpackagesfolder or withpaket.local, until the next full restore - fix:
paket restoreno longer skips as up to date when thepackagesfolder is missing, or when a restore since the last full one may have changed it: a restore of some projects or groups for anotherpaket.lock, one withpaket.localor--force, or a full one for anotherpaket.lockthat failed. A fullpaket restore --forcenow writespaket-files/paket.restore.cached - fix:
Paket.Restore.targetsandpaket.targetsread the closest.config/dotnet-tools.jsonand the closestdotnet-tools.jsonfrom the root up, instead of only the.config/dotnet-tools.jsonof the root, to know whether paket is a local tool, and only the paket tool counts, not another tool with apaketcommand - fix:
Paket.Restore.targetsandpaket.targetsno longer take a folder namedpaketin the root or in.paket, such as a project folder namedPaketon a case-insensitive file system, for a Paket installed with--tool-path - fix: The restore no longer rewrites
.paket/Paket.Restore.targetswhen only its line endings differ from the ones of Paket, as after a checkout with other line endings, which showed it as changed in git after each restore. The same goes for.paket/paket.targetsand the other files that the restore writes - fix: When the restore updates
.paket/Paket.Restore.targets, as for a new version of Paket, the file keeps its line endings instead of taking the ones of the machine that built Paket. The same goes for.paket/paket.targetsand the other files that the restore writes - fix: When
#r "paket:"in F# scripts runs the newest Paket .NET tool restored in the NuGet packages folder, as it does when it finds Paket neither installed with--tool-pathnor as a local or global tool, it takes a release before its prereleases: with 12.0.0 and 12.0.0-alpha001 restored, it runs 12.0.0 instead of 12.0.0-alpha001 - fix: Git dependencies restore again when the git cache doesn't have their repository yet, as on a fresh CI agent: since 11.0.0, Paket ran
git remote set-urlin the empty cache folder that its lock had created - #4461 - fix: The paket-files of a git dependency are checked out when the HEAD of its git cache names a branch that is gone, as after the repository renamed its default branch, instead of failing with "bad revision 'HEAD'"
- fix: A git dependency whose checkout failed, as for a file name too long for the file system, is cloned again at the next restore, instead of being taken for one with local changes or for an up-to-date one
- fix: A local git dependency without a branch, whose repository has no master, gets an error that suggests giving its branch, as in
git file:///path/to/repository main - fix: A process that Paket starts and that exits right away, such as a git command, the
build:command of a git dependency or a credential provider, no longer fails with "Start of process ... failed". For a local git repository, the error showed as "Could not find hash for ..." - fix: Local git dependencies with a Windows path, like
git file:///C:/code/repo, resolve again: since 11.0.0 and #4377, their path kept the/before the drive letter - fix: A broken git cache in
~/.paket/git/dbis set up again instead of making git change the repository of a parent folder, such as a dotfiles repository in the home folder, and the git cache works withsafe.bareRepository=explicit - fix: The path of a local git repository can escape characters, like
git file:///home/me/my%20repo, and its folder name is read from a Windows path that ends with\or doesn't exist yet, and from a path to the.gitfolder of the repository, likegit file:///home/me/repo/.git. Such a path used to give an empty or a whole path as the name of the git cache and paket-files folders. A repository at the root of a file system, which has no folder name, or whose path ends with.or.., fails with an error. A folder name that holds a%, likegit file:///home/me/100%25, is checked out too - fix: A paket-files folder of a git dependency that isn't a clone, as one committed with the project, is cloned again. Paket used to run its git commands on the repository of the project instead, and could check the dependency out over the project
- fix: A git dependency on an annotated tag is locked at the commit of the tag, not at the tag object, which made each restore download it again. A lock file that holds the tag object still restores, and gets the commit at the next update
- fix: Only the
.gitthat ends the name of a git repository, in any case as inRepo.GIT, is left out of its folder name, sogit https://github.com/me/me.github.io.gitgoes topaket-files/github.com/me/me.github.ioinstead ofmehub.io. The paket-files folder of a repository with.gitinside its name, or another case of.gitat its end, moves. A remote URL to the.gitfolder of a repository, likegit ssh://host/home/me/repo/.git, is named after the folder of the repository, as a local one is, instead of taking the paket-files folder of its owner - fix: The git cache of a repository is
~/.paket/git/db/<owner>/<project>, so that remote repositories of the same name from two owners no longer share one, and swap its branches on each fetch. Local repositories of the same folder name still share one. Each repository is cloned again once, andpaket clear-cacheremoves the old caches - fix:
paket convert-from-nugetremoves theNuGet.Config,NuGet.targetsandNuGet.exefiles of the root.nugetfolder again, as well as the folder once it is empty: Paket 11.0 had stopped finding them. It reads and removes theNuGet.Configof the root and of the.nugetfolder under the names NuGet looks for,nuget.config,NuGet.configorNuGet.Config, and theNuGet.targetsandNuGet.exeof the.nugetfolder whatever the case of their name, where Linux only found lowercase names - fix:
paket convert-from-nugetconverts and removes nothing through a link: it skips the projects, NuGet files and solutions of the folders that are links, with a warning for each such folder, so these projects are not converted. It leaves in place a.nugetfolder that is a link and the solutions that are links, and skips with a warning the solutions it cannot read or update, instead of failing - fix:
paket convert-from-nugetonly removes the solution items of a.slnthat are files it deletes, found by their path in any solution folder. It removed the first line naming a NuGet file of.nuget, even a project or apackages.configit kept - fix:
paket convert-from-nugetkeeps the non-ASCII characters of a.slnwithout a BOM, which it saved in ASCII - fix:
paket generate-load-scriptskeeps in the group scripts the assemblies that reference themselves, like System.Reactive 7.0, which it dropped. It also keeps, with a warning, the assemblies and packages that depend on each other, which it dropped too - #4458 - fix:
paket update --no-installno longer fails when a group hasgenerate_load_scripts: trueand the packages of the new paket.lock aren't all restored, as on a fresh checkout or for a package that the update adds: it leaves the load scripts to the next restore, which downloads the packages that they load - #2785 - fix:
paket pack --symbolsno longer fails on a project with Compile entries without anIncludeorUpdateattribute, such as<Compile Remove="..." />or a Compile item definition in anItemDefinitionGroup, and leaves out of the symbols package the files that a Remove names without wildcards - #4222 - fix: Looking for projects no longer runs forever on a cyclic directory link, as in a Nix
.devenvprofile.paket packstill follows the links when it looks for template files - #4421 @michaelglass - fix: Do not warn about missing "redirects: force" for FSharp.Core in projects targeting net5.0 and later - #4455
- fix:
paket installno longer warns about missing "redirects: force" for FSharp.Core in SDK projects that take their target framework from Directory.Build.props, by inheriting it or through a property such as$(DefaultTargetFramework). Paket, which doesn't read Directory.Build.props, also stops taking such a property for net10 (.NET Framework 1.0): where it needs the framework of the project, as forframework: auto-detectorpaket pack, it falls back to net40, like for a project without framework - #4485 - fix: The warning about the FSharp.Core binding redirects of F# projects links to an existing section of the documentation